diff options
Diffstat (limited to 'comphelper/source/misc')
59 files changed, 14985 insertions, 0 deletions
diff --git a/comphelper/source/misc/SelectionMultiplex.cxx b/comphelper/source/misc/SelectionMultiplex.cxx new file mode 100644 index 000000000000..82d6eb351af5 --- /dev/null +++ b/comphelper/source/misc/SelectionMultiplex.cxx @@ -0,0 +1,176 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include <comphelper/SelectionMultiplex.hxx> +#include <osl/diagnose.h> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::view; + +//======================================================================== +//= OSelectionChangeListener +//======================================================================== +//------------------------------------------------------------------------ +OSelectionChangeListener::~OSelectionChangeListener() +{ + if (m_pAdapter) + m_pAdapter->dispose(); +} + +//------------------------------------------------------------------ +void OSelectionChangeListener::_disposing(const EventObject&) throw( RuntimeException) +{ + // nothing to do here +} + +//------------------------------------------------------------------ +void OSelectionChangeListener::disposeAdapter() +{ + if ( m_pAdapter ) + m_pAdapter->dispose(); + + // will automatically set a new adapter + OSL_ENSURE( !m_pAdapter, "OSelectionChangeListener::disposeAdapter: what did dispose do?" ); +} + +//------------------------------------------------------------------ +void OSelectionChangeListener::setAdapter(OSelectionChangeMultiplexer* pAdapter) +{ + if (m_pAdapter) + { + ::osl::MutexGuard aGuard(m_rMutex); + m_pAdapter->release(); + m_pAdapter = NULL; + } + + if (pAdapter) + { + ::osl::MutexGuard aGuard(m_rMutex); + m_pAdapter = pAdapter; + m_pAdapter->acquire(); + } +} + +//======================================================================== +//= OSelectionChangeMultiplexer +//======================================================================== +//------------------------------------------------------------------ +OSelectionChangeMultiplexer::OSelectionChangeMultiplexer(OSelectionChangeListener* _pListener, const Reference< XSelectionSupplier>& _rxSet, sal_Bool _bAutoReleaseSet) + :m_xSet(_rxSet) + ,m_pListener(_pListener) + ,m_nLockCount(0) + ,m_bListening(sal_False) + ,m_bAutoSetRelease(_bAutoReleaseSet) +{ + m_pListener->setAdapter(this); + osl_incrementInterlockedCount(&m_refCount); + { + Reference< XSelectionChangeListener> xPreventDelete(this); + m_xSet->addSelectionChangeListener(xPreventDelete); + } + osl_decrementInterlockedCount(&m_refCount); +} + +//------------------------------------------------------------------ +OSelectionChangeMultiplexer::~OSelectionChangeMultiplexer() +{ +} + +//------------------------------------------------------------------ +void OSelectionChangeMultiplexer::lock() +{ + ++m_nLockCount; +} + +//------------------------------------------------------------------ +void OSelectionChangeMultiplexer::unlock() +{ + --m_nLockCount; +} + +//------------------------------------------------------------------ +void OSelectionChangeMultiplexer::dispose() +{ + if (m_bListening) + { + Reference< XSelectionChangeListener> xPreventDelete(this); + + m_xSet->removeSelectionChangeListener(xPreventDelete); + + m_pListener->setAdapter(NULL); + + m_pListener = NULL; + m_bListening = sal_False; + + if (m_bAutoSetRelease) + m_xSet = NULL; + } +} + +// XEventListener +//------------------------------------------------------------------ +void SAL_CALL OSelectionChangeMultiplexer::disposing( const EventObject& _rSource) throw( RuntimeException) +{ + if (m_pListener) + { + // tell the listener + if (!locked()) + m_pListener->_disposing(_rSource); + // disconnect the listener + if (m_pListener) // may have been reset whilest calling into _disposing + m_pListener->setAdapter(NULL); + } + + m_pListener = NULL; + m_bListening = sal_False; + + if (m_bAutoSetRelease) + m_xSet = NULL; +} + +// XSelectionChangeListener +//------------------------------------------------------------------ +void SAL_CALL OSelectionChangeMultiplexer::selectionChanged( const EventObject& _rEvent ) throw( RuntimeException) +{ + if (m_pListener && !locked()) + m_pListener->_selectionChanged(_rEvent); +} +//......................................................................... +} +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblecomponenthelper.cxx b/comphelper/source/misc/accessiblecomponenthelper.cxx new file mode 100644 index 000000000000..03991ddfc424 --- /dev/null +++ b/comphelper/source/misc/accessiblecomponenthelper.cxx @@ -0,0 +1,223 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/accessiblecomponenthelper.hxx> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::accessibility; + + //===================================================================== + //= OCommonAccessibleComponent + //===================================================================== + //--------------------------------------------------------------------- + OCommonAccessibleComponent::OCommonAccessibleComponent( ) + { + } + + //--------------------------------------------------------------------- + OCommonAccessibleComponent::OCommonAccessibleComponent( IMutex* _pExternalLock ) + :OAccessibleContextHelper( _pExternalLock ) + { + } + + //--------------------------------------------------------------------- + OCommonAccessibleComponent::~OCommonAccessibleComponent( ) + { + forgetExternalLock(); + // this ensures that the lock, which may be already destroyed as part of the derivee, + // is not used anymore + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OCommonAccessibleComponent::containsPoint( const Point& _rPoint ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + Rectangle aBounds( implGetBounds() ); + return ( _rPoint.X >= 0 ) + && ( _rPoint.Y >= 0 ) + && ( _rPoint.X < aBounds.Width ) + && ( _rPoint.Y < aBounds.Height ); + } + + //-------------------------------------------------------------------- + Point SAL_CALL OCommonAccessibleComponent::getLocation( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + Rectangle aBounds( implGetBounds() ); + return Point( aBounds.X, aBounds.Y ); + } + + //-------------------------------------------------------------------- + Point SAL_CALL OCommonAccessibleComponent::getLocationOnScreen( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + Rectangle aBounds( implGetBounds() ); + + Point aScreenLoc( 0, 0 ); + + Reference< XAccessibleComponent > xParentComponent( implGetParentContext(), UNO_QUERY ); + OSL_ENSURE( xParentComponent.is(), "OCommonAccessibleComponent::getLocationOnScreen: no parent component!" ); + if ( xParentComponent.is() ) + { + Point aParentScreenLoc( xParentComponent->getLocationOnScreen() ); + Point aOwnRelativeLoc( getLocation() ); + aScreenLoc.X = aParentScreenLoc.X + aOwnRelativeLoc.X; + aScreenLoc.Y = aParentScreenLoc.Y + aOwnRelativeLoc.Y; + } + + return aScreenLoc; + } + + //-------------------------------------------------------------------- + Size SAL_CALL OCommonAccessibleComponent::getSize( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + Rectangle aBounds( implGetBounds() ); + return Size( aBounds.Width, aBounds.Height ); + } + + //-------------------------------------------------------------------- + Rectangle SAL_CALL OCommonAccessibleComponent::getBounds( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + return implGetBounds(); + } + + //===================================================================== + //= OAccessibleComponentHelper + //===================================================================== + //--------------------------------------------------------------------- + OAccessibleComponentHelper::OAccessibleComponentHelper( ) + { + } + + //--------------------------------------------------------------------- + OAccessibleComponentHelper::OAccessibleComponentHelper( IMutex* _pExternalLock ) + :OCommonAccessibleComponent( _pExternalLock ) + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleComponentHelper, OCommonAccessibleComponent, OAccessibleComponentHelper_Base ) + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleComponentHelper, OCommonAccessibleComponent, OAccessibleComponentHelper_Base ) + // (order matters: the first is the class name, the second is the class doing the ref counting) + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OAccessibleComponentHelper::containsPoint( const Point& _rPoint ) throw (RuntimeException) + { + return OCommonAccessibleComponent::containsPoint( _rPoint ); + } + + //-------------------------------------------------------------------- + Point SAL_CALL OAccessibleComponentHelper::getLocation( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getLocation( ); + } + + //-------------------------------------------------------------------- + Point SAL_CALL OAccessibleComponentHelper::getLocationOnScreen( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getLocationOnScreen( ); + } + + //-------------------------------------------------------------------- + Size SAL_CALL OAccessibleComponentHelper::getSize( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getSize( ); + } + + //-------------------------------------------------------------------- + Rectangle SAL_CALL OAccessibleComponentHelper::getBounds( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getBounds( ); + } + + //===================================================================== + //= OAccessibleExtendedComponentHelper + //===================================================================== + //--------------------------------------------------------------------- + OAccessibleExtendedComponentHelper::OAccessibleExtendedComponentHelper( ) + { + } + + //--------------------------------------------------------------------- + OAccessibleExtendedComponentHelper::OAccessibleExtendedComponentHelper( IMutex* _pExternalLock ) + :OCommonAccessibleComponent( _pExternalLock ) + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleExtendedComponentHelper, OCommonAccessibleComponent, OAccessibleExtendedComponentHelper_Base ) + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleExtendedComponentHelper, OCommonAccessibleComponent, OAccessibleExtendedComponentHelper_Base ) + // (order matters: the first is the class name, the second is the class doing the ref counting) + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OAccessibleExtendedComponentHelper::containsPoint( const Point& _rPoint ) throw (RuntimeException) + { + return OCommonAccessibleComponent::containsPoint( _rPoint ); + } + + //-------------------------------------------------------------------- + Point SAL_CALL OAccessibleExtendedComponentHelper::getLocation( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getLocation( ); + } + + //-------------------------------------------------------------------- + Point SAL_CALL OAccessibleExtendedComponentHelper::getLocationOnScreen( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getLocationOnScreen( ); + } + + //-------------------------------------------------------------------- + Size SAL_CALL OAccessibleExtendedComponentHelper::getSize( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getSize( ); + } + + //-------------------------------------------------------------------- + Rectangle SAL_CALL OAccessibleExtendedComponentHelper::getBounds( ) throw (RuntimeException) + { + return OCommonAccessibleComponent::getBounds( ); + } + +//......................................................................... +} // namespace comphelper +//......................................................................... + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblecontexthelper.cxx b/comphelper/source/misc/accessiblecontexthelper.cxx new file mode 100644 index 000000000000..40baf72e69a9 --- /dev/null +++ b/comphelper/source/misc/accessiblecontexthelper.cxx @@ -0,0 +1,358 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/accessiblecontexthelper.hxx> +#include <comphelper/accessibleeventbuffer.hxx> +#include <osl/diagnose.h> +#include <cppuhelper/weakref.hxx> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <comphelper/accessibleeventnotifier.hxx> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::accessibility; + + //===================================================================== + //= OContextHelper_Impl + //===================================================================== + /** implementation class for OAccessibleContextHelper. No own thread safety! + */ + class OContextHelper_Impl + { + private: + OAccessibleContextHelper* m_pAntiImpl; // the owning instance + IMutex* m_pExternalLock; // the optional additional external lock + + ::cppu::OInterfaceContainerHelper* m_pEventListeners; + WeakReference< XAccessible > m_aCreator; // the XAccessible which created our XAccessibleContext + + AccessibleEventNotifier::TClientId m_nClientId; + + public: + inline Reference< XAccessible > getCreator( ) const { return m_aCreator; } + inline void setCreator( const Reference< XAccessible >& _rAcc ); + + inline IMutex* getExternalLock( ) { return m_pExternalLock; } + inline void setExternalLock( IMutex* _pLock ) { m_pExternalLock = _pLock; } + + inline AccessibleEventNotifier::TClientId + getClientId() const { return m_nClientId; } + inline void setClientId( const AccessibleEventNotifier::TClientId _nId ) + { m_nClientId = _nId; } + + public: + OContextHelper_Impl( OAccessibleContextHelper* _pAntiImpl ) + :m_pAntiImpl( _pAntiImpl ) + ,m_pExternalLock( NULL ) + ,m_pEventListeners( NULL ) + ,m_nClientId( 0 ) + { + } + }; + + //--------------------------------------------------------------------- + inline void OContextHelper_Impl::setCreator( const Reference< XAccessible >& _rAcc ) + { + m_aCreator = _rAcc; + } + + //===================================================================== + //= OAccessibleContextHelper + //===================================================================== + //--------------------------------------------------------------------- + OAccessibleContextHelper::OAccessibleContextHelper( ) + :OAccessibleContextHelper_Base( GetMutex() ) + ,m_pImpl( NULL ) + { + m_pImpl = new OContextHelper_Impl( this ); + } + + //--------------------------------------------------------------------- + OAccessibleContextHelper::OAccessibleContextHelper( IMutex* _pExternalLock ) + :OAccessibleContextHelper_Base( GetMutex() ) + ,m_pImpl( NULL ) + { + m_pImpl = new OContextHelper_Impl( this ); + m_pImpl->setExternalLock( _pExternalLock ); + } + + //--------------------------------------------------------------------- + void OAccessibleContextHelper::forgetExternalLock() + { + m_pImpl->setExternalLock( NULL ); + } + + //--------------------------------------------------------------------- + OAccessibleContextHelper::~OAccessibleContextHelper( ) + { + forgetExternalLock(); + // this ensures that the lock, which may be already destroyed as part of the derivee, + // is not used anymore + + ensureDisposed(); + + delete m_pImpl; + m_pImpl = NULL; + } + + //--------------------------------------------------------------------- + IMutex* OAccessibleContextHelper::getExternalLock( ) + { + return m_pImpl->getExternalLock(); + } + + //--------------------------------------------------------------------- + void SAL_CALL OAccessibleContextHelper::disposing() + { + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + + if ( m_pImpl->getClientId( ) ) + { + AccessibleEventNotifier::revokeClientNotifyDisposing( m_pImpl->getClientId( ), *this ); + m_pImpl->setClientId( 0 ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OAccessibleContextHelper::addEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException) + { + OMutexGuard aGuard( getExternalLock() ); + // don't use the OContextEntryGuard - it will throw an exception if we're not alive + // anymore, while the most recent specification for XComponent states that we should + // silently ignore the call in such a situation + if ( !isAlive() ) + { + if ( _rxListener.is() ) + _rxListener->disposing( EventObject( *this ) ); + return; + } + + if ( _rxListener.is() ) + { + if ( !m_pImpl->getClientId( ) ) + m_pImpl->setClientId( AccessibleEventNotifier::registerClient( ) ); + + AccessibleEventNotifier::addEventListener( m_pImpl->getClientId( ), _rxListener ); + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OAccessibleContextHelper::removeEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException) + { + OMutexGuard aGuard( getExternalLock() ); + // don't use the OContextEntryGuard - it will throw an exception if we're not alive + // anymore, while the most recent specification for XComponent states that we should + // silently ignore the call in such a situation + if ( !isAlive() ) + return; + + if ( _rxListener.is() ) + { + sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( m_pImpl->getClientId( ), _rxListener ); + if ( !nListenerCount ) + { + // no listeners anymore + // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), + // and at least to us not firing any events anymore, in case somebody calls + // NotifyAccessibleEvent, again + AccessibleEventNotifier::revokeClient( m_pImpl->getClientId( ) ); + m_pImpl->setClientId( 0 ); + } + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OAccessibleContextHelper::NotifyAccessibleEvent( const sal_Int16 _nEventId, + const Any& _rOldValue, const Any& _rNewValue ) + { + if ( !m_pImpl->getClientId( ) ) + // if we don't have a client id for the notifier, then we don't have listeners, then + // we don't need to notify anything + return; + + // build an event object + AccessibleEventObject aEvent; + aEvent.Source = *this; + aEvent.EventId = _nEventId; + aEvent.OldValue = _rOldValue; + aEvent.NewValue = _rNewValue; + + // let the notifier handle this event + AccessibleEventNotifier::addEvent( m_pImpl->getClientId( ), aEvent ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OAccessibleContextHelper::BufferAccessibleEvent( const sal_Int16 _nEventId, + const Any& _rOldValue, const Any& _rNewValue, + AccessibleEventBuffer & _rBuffer ) + { + // TODO: this whole method (as well as the class AccessibleEventBuffer) should be removed + // The reasons why they have been introduces id that we needed to collect a set of events + // before notifying them alltogether (after releasing our mutex). With the other + // NotifyAccessibleEvent being asynchronous now, this should not be necessary anymore + // - clients could use the other version now. + + // copy our current listeners + Sequence< Reference< XInterface > > aListeners; + if ( m_pImpl->getClientId( ) ) + aListeners = AccessibleEventNotifier::getEventListeners( m_pImpl->getClientId( ) ); + + if ( aListeners.getLength() ) + { + AccessibleEventObject aEvent; + aEvent.Source = *this; + OSL_ENSURE( aEvent.Source.is(), "OAccessibleContextHelper::BufferAccessibleEvent: invalid creator!" ); + aEvent.EventId = _nEventId; + aEvent.OldValue = _rOldValue; + aEvent.NewValue = _rNewValue; + + _rBuffer.addEvent( aEvent, aListeners ); + } + } + + //--------------------------------------------------------------------- + sal_Bool OAccessibleContextHelper::isAlive() const + { + return !GetBroadcastHelper().bDisposed && !GetBroadcastHelper().bInDispose; + } + + //--------------------------------------------------------------------- + void OAccessibleContextHelper::ensureAlive() const SAL_THROW( ( DisposedException ) ) + { + if( !isAlive() ) + throw DisposedException(); + } + + //--------------------------------------------------------------------- + void OAccessibleContextHelper::ensureDisposed( ) + { + if ( !GetBroadcastHelper().bDisposed ) + { + OSL_ENSURE( 0 == m_refCount, "OAccessibleContextHelper::ensureDisposed: this method _has_ to be called from without your dtor only!" ); + acquire(); + dispose(); + } + } + + //--------------------------------------------------------------------- + void OAccessibleContextHelper::lateInit( const Reference< XAccessible >& _rxAccessible ) + { + m_pImpl->setCreator( _rxAccessible ); + } + + //--------------------------------------------------------------------- + Reference< XAccessible > OAccessibleContextHelper::getAccessibleCreator( ) const + { + return m_pImpl->getCreator(); + } + + //--------------------------------------------------------------------- + sal_Int32 SAL_CALL OAccessibleContextHelper::getAccessibleIndexInParent( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + + // -1 for child not found/no parent (according to specification) + sal_Int32 nRet = -1; + + try + { + + Reference< XAccessibleContext > xParentContext( implGetParentContext() ); + + // iterate over parent's children and search for this object + if ( xParentContext.is() ) + { + // our own XAccessible for comparing with the children of our parent + Reference< XAccessible > xCreator( m_pImpl->getCreator() ); + + OSL_ENSURE( xCreator.is(), "OAccessibleContextHelper::getAccessibleIndexInParent: invalid creator!" ); + // two ideas why this could be NULL: + // * nobody called our late ctor (init), so we never had a creator at all -> bad + // * the creator is already dead. In this case, we should have been disposed, and + // never survived the above OContextEntryGuard. + // in all other situations the creator should be non-NULL + + if ( xCreator.is() ) + { + sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); + for ( sal_Int32 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild ) + { + Reference< XAccessible > xChild( xParentContext->getAccessibleChild( nChild ) ); + if ( xChild.get() == xCreator.get() ) + nRet = nChild; + } + } + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OAccessibleContextHelper::getAccessibleIndexInParent: caught an exception!" ); + } + + return nRet; + } + + //--------------------------------------------------------------------- + Locale SAL_CALL OAccessibleContextHelper::getLocale( ) throw (IllegalAccessibleComponentStateException, RuntimeException) + { + // simply ask the parent + Reference< XAccessible > xParent = getAccessibleParent(); + Reference< XAccessibleContext > xParentContext; + if ( xParent.is() ) + xParentContext = xParent->getAccessibleContext(); + + if ( !xParentContext.is() ) + throw IllegalAccessibleComponentStateException( ::rtl::OUString(), *this ); + + return xParentContext->getLocale(); + } + + //--------------------------------------------------------------------- + Reference< XAccessibleContext > OAccessibleContextHelper::implGetParentContext() SAL_THROW( ( RuntimeException ) ) + { + Reference< XAccessible > xParent = getAccessibleParent(); + Reference< XAccessibleContext > xParentContext; + if ( xParent.is() ) + xParentContext = xParent->getAccessibleContext(); + return xParentContext; + } + +//......................................................................... +} // namespace comphelper +//......................................................................... + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessibleeventbuffer.cxx b/comphelper/source/misc/accessibleeventbuffer.cxx new file mode 100644 index 000000000000..de3a4a736c55 --- /dev/null +++ b/comphelper/source/misc/accessibleeventbuffer.cxx @@ -0,0 +1,113 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/accessibleeventbuffer.hxx" + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/accessibility/AccessibleEventObject.hpp" +#include "com/sun/star/accessibility/XAccessibleEventListener.hpp" +#include "osl/diagnose.h" +#include "rtl/textenc.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +namespace css = ::com::sun::star; + +using comphelper::AccessibleEventBuffer; + +struct AccessibleEventBuffer::Entry +{ + inline Entry(::css::accessibility::AccessibleEventObject const & rEvent, + ::css::uno::Sequence< ::css::uno::Reference< + ::css::uno::XInterface > > const & rListeners): + m_aEvent(rEvent), m_aListeners(rListeners) {} + + ::css::accessibility::AccessibleEventObject m_aEvent; + + ::css::uno::Sequence< + ::css::uno::Reference< ::css::uno::XInterface > > m_aListeners; +}; + +AccessibleEventBuffer::AccessibleEventBuffer() +{} + +AccessibleEventBuffer::AccessibleEventBuffer( + AccessibleEventBuffer const & rOther): + m_aEntries(rOther.m_aEntries) +{} + +AccessibleEventBuffer::~AccessibleEventBuffer() +{} + +AccessibleEventBuffer +AccessibleEventBuffer::operator =(AccessibleEventBuffer const & rOther) +{ + m_aEntries = rOther.m_aEntries; + return *this; +} + +void AccessibleEventBuffer::addEvent( + ::css::accessibility::AccessibleEventObject const & rEvent, + ::css::uno::Sequence< ::css::uno::Reference< ::css::uno::XInterface > > + const & rListeners) +{ + m_aEntries.push_back(Entry(rEvent, rListeners)); +} + +void AccessibleEventBuffer::sendEvents() const +{ + for (Entries::const_iterator aIt(m_aEntries.begin()); + aIt != m_aEntries.end(); ++aIt) + for (::sal_Int32 i = 0; i < aIt->m_aListeners.getLength(); ++i) + { + ::css::uno::Reference< + ::css::accessibility::XAccessibleEventListener > xListener( + aIt->m_aListeners[i], ::css::uno::UNO_QUERY); + if (xListener.is()) + try + { + xListener->notifyEvent(aIt->m_aEvent); + } + catch (::css::uno::RuntimeException & rEx) + { + OSL_TRACE( + "comphelper::AccessibleEventBuffer::sendEvents:" + " caught %s\n", + ::rtl::OUStringToOString( + rEx.Message, RTL_TEXTENCODING_UTF8).getStr()); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessibleeventnotifier.cxx b/comphelper/source/misc/accessibleeventnotifier.cxx new file mode 100644 index 000000000000..1e8607e73ebf --- /dev/null +++ b/comphelper/source/misc/accessibleeventnotifier.cxx @@ -0,0 +1,261 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/accessibleeventnotifier.hxx> +#include <osl/diagnose.h> +#include <rtl/instance.hxx> +#include <comphelper/guarding.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::accessibility; +using namespace ::comphelper; + +//===================================================================== +//= AccessibleEventNotifier +//===================================================================== +//--------------------------------------------------------------------- +namespace +{ + struct lclMutex + : public rtl::Static< ::osl::Mutex, lclMutex > {}; + struct Clients + : public rtl::Static< AccessibleEventNotifier::ClientMap, Clients > {}; +} + +//......................................................................... +namespace comphelper +{ +//......................................................................... + + //--------------------------------------------------------------------- + AccessibleEventNotifier::TClientId AccessibleEventNotifier::generateId() + { + TClientId nBiggestUsedId = 0; + TClientId nFreeId = 0; + + // look through all registered clients until we find a "gap" in the ids + + // Note that the following relies on the fact the elements in the map are traveled with + // ascending keys (aka client ids) + AccessibleEventNotifier::ClientMap &rClients = Clients::get(); + for ( ClientMap::const_iterator aLookup = rClients.begin(); + aLookup != rClients.end(); + ++aLookup + ) + { + TClientId nCurrent = aLookup->first; + OSL_ENSURE( nCurrent > nBiggestUsedId, "AccessibleEventNotifier::generateId: map is expected to be sorted ascending!" ); + + if ( nCurrent - nBiggestUsedId > 1 ) + { // found a "gap" + nFreeId = nBiggestUsedId + 1; + break; + } + + nBiggestUsedId = nCurrent; + } + + if ( !nFreeId ) + nFreeId = nBiggestUsedId + 1; + + OSL_ENSURE( rClients.end() == rClients.find( nFreeId ), + "AccessibleEventNotifier::generateId: algorithm broken!" ); + + return nFreeId; + } + + //--------------------------------------------------------------------- + AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient( ) + { + ::osl::MutexGuard aGuard( lclMutex::get() ); + + // generate a new client id + TClientId nNewClientId = generateId( ); + + // the event listeners for the new client + EventListeners* pNewListeners = new EventListeners( lclMutex::get() ); + // note that we're using our own mutex here, so the listener containers for all + // our clients share this same mutex. + // this is a reminiscense to the days where the notifier was asynchronous. Today this is + // completely nonsense, and potentially slowing down the Office me thinks ... + + // add the client + Clients::get().insert( ClientMap::value_type( nNewClientId, pNewListeners ) ); + + // outta here + return nNewClientId; + } + + //--------------------------------------------------------------------- + sal_Bool AccessibleEventNotifier::implLookupClient( const TClientId _nClient, ClientMap::iterator& _rPos ) + { + // look up this client + AccessibleEventNotifier::ClientMap &rClients = Clients::get(); + _rPos = rClients.find( _nClient ); + OSL_ENSURE( rClients.end() != _rPos, "AccessibleEventNotifier::implLookupClient: invalid client id (did you register your client?)!" ); + + return ( rClients.end() != _rPos ); + } + + //--------------------------------------------------------------------- + void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) + { + ::osl::MutexGuard aGuard( lclMutex::get() ); + + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return; + + // remove it from the clients map + delete aClientPos->second; + Clients::get().erase( aClientPos ); + } + + //--------------------------------------------------------------------- + void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient, + const Reference< XInterface >& _rxEventSource ) SAL_THROW( ( ) ) + { + ::osl::MutexGuard aGuard( lclMutex::get() ); + + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return; + + // notify the "disposing" event for this client + EventObject aDisposalEvent; + aDisposalEvent.Source = _rxEventSource; + + // notify the listeners + EventListeners* pListeners = aClientPos->second; + + // we do not need the entry in the clients map anymore + // (do this before actually notifying, because some client implementations have re-entrance + // problems and call into revokeClient while we are notifying from hereing) + Clients::get().erase( aClientPos ); + + // now really do the notification + pListeners->disposeAndClear( aDisposalEvent ); + delete pListeners; + + } + + //--------------------------------------------------------------------- + sal_Int32 AccessibleEventNotifier::addEventListener( + const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) ) + { + ::osl::MutexGuard aGuard( lclMutex::get() ); + + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return 0; + + if ( _rxListener.is() ) + aClientPos->second->addInterface( _rxListener ); + + return aClientPos->second->getLength(); + } + + //--------------------------------------------------------------------- + sal_Int32 AccessibleEventNotifier::removeEventListener( + const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) ) + { + ::osl::MutexGuard aGuard( lclMutex::get() ); + + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return 0; + + if ( _rxListener.is() ) + aClientPos->second->removeInterface( _rxListener ); + + return aClientPos->second->getLength(); + } + + //--------------------------------------------------------------------- + Sequence< Reference< XInterface > > AccessibleEventNotifier::getEventListeners( const TClientId _nClient ) SAL_THROW( ( ) ) + { + Sequence< Reference< XInterface > > aListeners; + + ::osl::MutexGuard aGuard( lclMutex::get() ); + + ClientMap::iterator aClientPos; + if ( implLookupClient( _nClient, aClientPos ) ) + aListeners = aClientPos->second->getElements(); + + return aListeners; + } + + //--------------------------------------------------------------------- + void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) SAL_THROW( ( ) ) + { + Sequence< Reference< XInterface > > aListeners; + + // --- <mutex lock> ------------------------------- + { + ::osl::MutexGuard aGuard( lclMutex::get() ); + + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return; + + // since we're synchronous, again, we want to notify immediately + aListeners = aClientPos->second->getElements(); + } + // --- </mutex lock> ------------------------------ + + // default handling: loop through all listeners, and notify them + const Reference< XInterface >* pListeners = aListeners.getConstArray(); + const Reference< XInterface >* pListenersEnd = pListeners + aListeners.getLength(); + while ( pListeners != pListenersEnd ) + { + try + { + static_cast< XAccessibleEventListener* >( pListeners->get() )->notifyEvent( _rEvent ); + } + catch( const Exception& ) + { + // no assertion, because a broken access remote bridge or something like this + // can cause this exception + } + ++pListeners; + } + } + +//......................................................................... +} // namespace comphelper +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblekeybindinghelper.cxx b/comphelper/source/misc/accessiblekeybindinghelper.cxx new file mode 100644 index 000000000000..07e1e11949cb --- /dev/null +++ b/comphelper/source/misc/accessiblekeybindinghelper.cxx @@ -0,0 +1,117 @@ +/* -*- 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 + * <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_comphelper.hxx" + +// includes -------------------------------------------------------------- +#include <comphelper/accessiblekeybindinghelper.hxx> + + +//.............................................................................. +namespace comphelper +{ +//.............................................................................. + + using namespace ::com::sun::star; // MT 04/2003: was ::drafts::com::sun::star - otherwise to many changes + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::accessibility; + + //============================================================================== + // OAccessibleKeyBindingHelper + //============================================================================== + + OAccessibleKeyBindingHelper::OAccessibleKeyBindingHelper() + { + } + + // ----------------------------------------------------------------------------- + + OAccessibleKeyBindingHelper::OAccessibleKeyBindingHelper( const OAccessibleKeyBindingHelper& rHelper ) + : cppu::WeakImplHelper1<XAccessibleKeyBinding>( rHelper ) + , m_aKeyBindings( rHelper.m_aKeyBindings ) + { + } + + // ----------------------------------------------------------------------------- + + OAccessibleKeyBindingHelper::~OAccessibleKeyBindingHelper() + { + } + + // ----------------------------------------------------------------------------- + + void OAccessibleKeyBindingHelper::AddKeyBinding( const Sequence< awt::KeyStroke >& rKeyBinding ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + m_aKeyBindings.push_back( rKeyBinding ); + } + + // ----------------------------------------------------------------------------- + + void OAccessibleKeyBindingHelper::AddKeyBinding( const awt::KeyStroke& rKeyStroke ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + Sequence< awt::KeyStroke > aSeq(1); + aSeq[0] = rKeyStroke; + m_aKeyBindings.push_back( aSeq ); + } + + // ----------------------------------------------------------------------------- + // XAccessibleKeyBinding + // ----------------------------------------------------------------------------- + + sal_Int32 OAccessibleKeyBindingHelper::getAccessibleKeyBindingCount() throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aKeyBindings.size(); + } + + // ----------------------------------------------------------------------------- + + Sequence< awt::KeyStroke > OAccessibleKeyBindingHelper::getAccessibleKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( nIndex < 0 || nIndex >= (sal_Int32)m_aKeyBindings.size() ) + throw IndexOutOfBoundsException(); + + return m_aKeyBindings[nIndex]; + } + + // ----------------------------------------------------------------------------- + +//.............................................................................. +} // namespace comphelper +//.............................................................................. + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessibleselectionhelper.cxx b/comphelper/source/misc/accessibleselectionhelper.cxx new file mode 100644 index 000000000000..88d0c35159b7 --- /dev/null +++ b/comphelper/source/misc/accessibleselectionhelper.cxx @@ -0,0 +1,194 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/accessibleselectionhelper.hxx> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::awt; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::accessibility; + + //===================================================================== + //= OCommonAccessibleSelection + //===================================================================== + //--------------------------------------------------------------------- + OCommonAccessibleSelection::OCommonAccessibleSelection( ) + { + } + + //-------------------------------------------------------------------- + void SAL_CALL OCommonAccessibleSelection::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + implSelect( nChildIndex, sal_True ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OCommonAccessibleSelection::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + return( implIsSelected( nChildIndex ) ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCommonAccessibleSelection::clearAccessibleSelection( ) throw (RuntimeException) + { + implSelect( ACCESSIBLE_SELECTION_CHILD_ALL, sal_False ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCommonAccessibleSelection::selectAllAccessibleChildren( ) throw (RuntimeException) + { + implSelect( ACCESSIBLE_SELECTION_CHILD_ALL, sal_True ); + } + + //-------------------------------------------------------------------- + sal_Int32 SAL_CALL OCommonAccessibleSelection::getSelectedAccessibleChildCount( ) throw (RuntimeException) + { + sal_Int32 nRet = 0; + Reference< XAccessibleContext > xParentContext( implGetAccessibleContext() ); + + OSL_ENSURE( xParentContext.is(), "OCommonAccessibleSelection::getSelectedAccessibleChildCount: no parent context!" ); + + if( xParentContext.is() ) + { + for( sal_Int32 i = 0, nChildCount = xParentContext->getAccessibleChildCount(); i < nChildCount; i++ ) + if( implIsSelected( i ) ) + ++nRet; + } + + return( nRet ); + } + + //-------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OCommonAccessibleSelection::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + Reference< XAccessible > xRet; + Reference< XAccessibleContext > xParentContext( implGetAccessibleContext() ); + + OSL_ENSURE( xParentContext.is(), "OCommonAccessibleSelection::getSelectedAccessibleChildCount: no parent context!" ); + + if( xParentContext.is() ) + { + for( sal_Int32 i = 0, nChildCount = xParentContext->getAccessibleChildCount(), nPos = 0; ( i < nChildCount ) && !xRet.is(); i++ ) + if( implIsSelected( i ) && ( nPos++ == nSelectedChildIndex ) ) + xRet = xParentContext->getAccessibleChild( i ); + } + + return( xRet ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCommonAccessibleSelection::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + implSelect( nSelectedChildIndex, sal_False ); + } + + //===================================================================== + //= OAccessibleSelectionHelper + //===================================================================== + //--------------------------------------------------------------------- + OAccessibleSelectionHelper::OAccessibleSelectionHelper( ) + { + } + + //-------------------------------------------------------------------- + OAccessibleSelectionHelper::OAccessibleSelectionHelper( IMutex* _pExternalLock ) : OAccessibleComponentHelper(_pExternalLock) + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleSelectionHelper, OAccessibleComponentHelper, OAccessibleSelectionHelper_Base ) + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleSelectionHelper, OAccessibleComponentHelper, OAccessibleSelectionHelper_Base ) + // (order matters: the first is the class name, the second is the class doing the ref counting) + + //-------------------------------------------------------------------- + Reference< XAccessibleContext > OAccessibleSelectionHelper::implGetAccessibleContext() throw ( RuntimeException ) + { + return( this ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleSelectionHelper::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + OCommonAccessibleSelection::selectAccessibleChild( nChildIndex ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OAccessibleSelectionHelper::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + return( OCommonAccessibleSelection::isAccessibleChildSelected( nChildIndex ) ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleSelectionHelper::clearAccessibleSelection( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + OCommonAccessibleSelection::clearAccessibleSelection(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleSelectionHelper::selectAllAccessibleChildren( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + OCommonAccessibleSelection::selectAllAccessibleChildren(); + } + + //-------------------------------------------------------------------- + sal_Int32 SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChildCount( ) throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + return( OCommonAccessibleSelection::getSelectedAccessibleChildCount() ); + } + + //-------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + return( OCommonAccessibleSelection::getSelectedAccessibleChild( nSelectedChildIndex ) ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleSelectionHelper::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + OCommonAccessibleSelection::deselectAccessibleChild( nSelectedChildIndex ); + } + +//......................................................................... +} // namespace comphelper +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessibletexthelper.cxx b/comphelper/source/misc/accessibletexthelper.cxx new file mode 100644 index 000000000000..6edc3df43020 --- /dev/null +++ b/comphelper/source/misc/accessibletexthelper.cxx @@ -0,0 +1,916 @@ +/* -*- 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 + * <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_comphelper.hxx" + +// includes -------------------------------------------------------------- +#include <comphelper/accessibletexthelper.hxx> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/i18n/CharacterIteratorMode.hpp> +#include <com/sun/star/i18n/WordType.hpp> +#include <com/sun/star/i18n/KCharacterType.hpp> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/accessibility/TextSegment.hpp> + +#include <algorithm> + +//.............................................................................. +namespace comphelper +{ +//.............................................................................. + + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::accessibility; + + //============================================================================== + // OCommonAccessibleText + //============================================================================== + + OCommonAccessibleText::OCommonAccessibleText() + { + } + + // ----------------------------------------------------------------------------- + + OCommonAccessibleText::~OCommonAccessibleText() + { + } + + // ----------------------------------------------------------------------------- + + Reference < i18n::XBreakIterator > OCommonAccessibleText::implGetBreakIterator() + { + if ( !m_xBreakIter.is() ) + { + Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); + if ( xMSF.is() ) + { + m_xBreakIter = Reference< i18n::XBreakIterator > + ( xMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) ) ), UNO_QUERY ); + } + } + + return m_xBreakIter; + } + + // ----------------------------------------------------------------------------- + + Reference < i18n::XCharacterClassification > OCommonAccessibleText::implGetCharacterClassification() + { + if ( !m_xCharClass.is() ) + { + Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); + if ( xMSF.is() ) + { + m_xCharClass = Reference< i18n::XCharacterClassification > + ( xMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.CharacterClassification" ) ) ), UNO_QUERY ); + } + } + + return m_xCharClass; + } + + // ----------------------------------------------------------------------------- + + sal_Bool OCommonAccessibleText::implIsValidBoundary( i18n::Boundary& rBoundary, sal_Int32 nLength ) + { + return ( rBoundary.startPos >= 0 ) && ( rBoundary.startPos < nLength ) && ( rBoundary.endPos >= 0 ) && ( rBoundary.endPos <= nLength ); + } + + // ----------------------------------------------------------------------------- + + sal_Bool OCommonAccessibleText::implIsValidIndex( sal_Int32 nIndex, sal_Int32 nLength ) + { + return ( nIndex >= 0 ) && ( nIndex < nLength ); + } + + // ----------------------------------------------------------------------------- + + sal_Bool OCommonAccessibleText::implIsValidRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex, sal_Int32 nLength ) + { + return ( nStartIndex >= 0 ) && ( nStartIndex <= nLength ) && ( nEndIndex >= 0 ) && ( nEndIndex <= nLength ); + } + + // ----------------------------------------------------------------------------- + + void OCommonAccessibleText::implGetGlyphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex ) + { + ::rtl::OUString sText( implGetText() ); + + if ( implIsValidIndex( nIndex, sText.getLength() ) ) + { + Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator(); + if ( xBreakIter.is() ) + { + sal_Int32 nCount = 1; + sal_Int32 nDone; + sal_Int32 nStartIndex = xBreakIter->previousCharacters( sText, nIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone ); + if ( nDone != 0 ) + nStartIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone ); + sal_Int32 nEndIndex = xBreakIter->nextCharacters( sText, nStartIndex, implGetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nDone ); + if ( nDone != 0 ) + { + rBoundary.startPos = nStartIndex; + rBoundary.endPos = nEndIndex; + } + } + } + else + { + rBoundary.startPos = nIndex; + rBoundary.endPos = nIndex; + } + } + + // ----------------------------------------------------------------------------- + + sal_Bool OCommonAccessibleText::implGetWordBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex ) + { + sal_Bool bWord = sal_False; + ::rtl::OUString sText( implGetText() ); + + if ( implIsValidIndex( nIndex, sText.getLength() ) ) + { + Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator(); + if ( xBreakIter.is() ) + { + rBoundary = xBreakIter->getWordBoundary( sText, nIndex, implGetLocale(), i18n::WordType::ANY_WORD, sal_True ); + + // it's a word, if the first character is an alpha-numeric character + Reference< i18n::XCharacterClassification > xCharClass = implGetCharacterClassification(); + if ( xCharClass.is() ) + { + sal_Int32 nType = xCharClass->getCharacterType( sText, rBoundary.startPos, implGetLocale() ); + if ( ( nType & ( i18n::KCharacterType::LETTER | i18n::KCharacterType::DIGIT ) ) != 0 ) + bWord = sal_True; + } + } + } + else + { + rBoundary.startPos = nIndex; + rBoundary.endPos = nIndex; + } + + return bWord; + } + + // ----------------------------------------------------------------------------- + + void OCommonAccessibleText::implGetSentenceBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex ) + { + ::rtl::OUString sText( implGetText() ); + + if ( implIsValidIndex( nIndex, sText.getLength() ) ) + { + Locale aLocale = implGetLocale(); + Reference < i18n::XBreakIterator > xBreakIter = implGetBreakIterator(); + if ( xBreakIter.is() ) + { + rBoundary.endPos = xBreakIter->endOfSentence( sText, nIndex, aLocale ); + rBoundary.startPos = xBreakIter->beginOfSentence( sText, rBoundary.endPos, aLocale ); + } + } + else + { + rBoundary.startPos = nIndex; + rBoundary.endPos = nIndex; + } + } + + // ----------------------------------------------------------------------------- + + void OCommonAccessibleText::implGetParagraphBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex ) + { + ::rtl::OUString sText( implGetText() ); + + if ( implIsValidIndex( nIndex, sText.getLength() ) ) + { + rBoundary.startPos = 0; + rBoundary.endPos = sText.getLength(); + + sal_Int32 nFound = sText.lastIndexOf( (sal_Unicode)'\n', nIndex ); + if ( nFound != -1 ) + rBoundary.startPos = nFound + 1; + + nFound = sText.indexOf( (sal_Unicode)'\n', nIndex ); + if ( nFound != -1 ) + rBoundary.endPos = nFound + 1; + } + else + { + rBoundary.startPos = nIndex; + rBoundary.endPos = nIndex; + } + } + + // ----------------------------------------------------------------------------- + + void OCommonAccessibleText::implGetLineBoundary( i18n::Boundary& rBoundary, sal_Int32 nIndex ) + { + ::rtl::OUString sText( implGetText() ); + sal_Int32 nLength = sText.getLength(); + + if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength ) + { + rBoundary.startPos = 0; + rBoundary.endPos = nLength; + } + else + { + rBoundary.startPos = nIndex; + rBoundary.endPos = nIndex; + } + } + + // ----------------------------------------------------------------------------- + + sal_Unicode OCommonAccessibleText::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + ::rtl::OUString sText( implGetText() ); + + if ( !implIsValidIndex( nIndex, sText.getLength() ) ) + throw IndexOutOfBoundsException(); + + return sText.getStr()[nIndex]; + } + + // ----------------------------------------------------------------------------- + + sal_Int32 OCommonAccessibleText::getCharacterCount() throw (RuntimeException) + { + return implGetText().getLength(); + } + + // ----------------------------------------------------------------------------- + + ::rtl::OUString OCommonAccessibleText::getSelectedText() throw (RuntimeException) + { + ::rtl::OUString sText; + sal_Int32 nStartIndex; + sal_Int32 nEndIndex; + + implGetSelection( nStartIndex, nEndIndex ); + + try + { + sText = getTextRange( nStartIndex, nEndIndex ); + } + catch ( IndexOutOfBoundsException& ) + { + } + + return sText; + } + + // ----------------------------------------------------------------------------- + + sal_Int32 OCommonAccessibleText::getSelectionStart() throw (RuntimeException) + { + sal_Int32 nStartIndex; + sal_Int32 nEndIndex; + + implGetSelection( nStartIndex, nEndIndex ); + + return nStartIndex; + } + + // ----------------------------------------------------------------------------- + + sal_Int32 OCommonAccessibleText::getSelectionEnd() throw (RuntimeException) + { + sal_Int32 nStartIndex; + sal_Int32 nEndIndex; + + implGetSelection( nStartIndex, nEndIndex ); + + return nEndIndex; + } + + // ----------------------------------------------------------------------------- + + ::rtl::OUString OCommonAccessibleText::getText() throw (RuntimeException) + { + return implGetText(); + } + + // ----------------------------------------------------------------------------- + + ::rtl::OUString OCommonAccessibleText::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + ::rtl::OUString sText( implGetText() ); + + if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) ) + throw IndexOutOfBoundsException(); + + sal_Int32 nMinIndex = ::std::min( nStartIndex, nEndIndex ); + sal_Int32 nMaxIndex = ::std::max( nStartIndex, nEndIndex ); + + return sText.copy( nMinIndex, nMaxIndex - nMinIndex ); + } + + // ----------------------------------------------------------------------------- + + TextSegment OCommonAccessibleText::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException) + { + ::rtl::OUString sText( implGetText() ); + sal_Int32 nLength = sText.getLength(); + + if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength ) + throw IndexOutOfBoundsException(); + + i18n::Boundary aBoundary; + TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch ( aTextType ) + { + case AccessibleTextType::CHARACTER: + { + if ( implIsValidIndex( nIndex, nLength ) ) + { + aResult.SegmentText = sText.copy( nIndex, 1 ); + aResult.SegmentStart = nIndex; + aResult.SegmentEnd = nIndex+1; + } + } + break; + case AccessibleTextType::GLYPH: + { + // get glyph at index + implGetGlyphBoundary( aBoundary, nIndex ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::WORD: + { + // get word at index + sal_Bool bWord = implGetWordBoundary( aBoundary, nIndex ); + if ( bWord && implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::SENTENCE: + { + // get sentence at index + implGetSentenceBoundary( aBoundary, nIndex ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::PARAGRAPH: + { + // get paragraph at index + implGetParagraphBoundary( aBoundary, nIndex ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::LINE: + { + // get line at index + implGetLineBoundary( aBoundary, nIndex ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::ATTRIBUTE_RUN: + { + // TODO: implGetAttributeRunBoundary() (incompatible!) + + aResult.SegmentText = sText; + aResult.SegmentStart = 0; + aResult.SegmentEnd = nLength; + } + break; + default: + { + // unknown text type + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + TextSegment OCommonAccessibleText::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException) + { + ::rtl::OUString sText( implGetText() ); + sal_Int32 nLength = sText.getLength(); + + if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength ) + throw IndexOutOfBoundsException(); + + i18n::Boundary aBoundary; + TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch ( aTextType ) + { + case AccessibleTextType::CHARACTER: + { + if ( implIsValidIndex( nIndex - 1, nLength ) ) + { + aResult.SegmentText = sText.copy( nIndex - 1, 1 ); + aResult.SegmentStart = nIndex-1; + aResult.SegmentEnd = nIndex; + } + } + break; + case AccessibleTextType::GLYPH: + { + // get glyph at index + implGetGlyphBoundary( aBoundary, nIndex ); + // get previous glyph + if ( aBoundary.startPos > 0 ) + { + implGetGlyphBoundary( aBoundary, aBoundary.startPos - 1 ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + } + break; + case AccessibleTextType::WORD: + { + // get word at index + implGetWordBoundary( aBoundary, nIndex ); + // get previous word + sal_Bool bWord = sal_False; + while ( !bWord && aBoundary.startPos > 0 ) + bWord = implGetWordBoundary( aBoundary, aBoundary.startPos - 1 ); + if ( bWord && implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::SENTENCE: + { + // get sentence at index + implGetSentenceBoundary( aBoundary, nIndex ); + // get previous sentence + if ( aBoundary.startPos > 0 ) + { + implGetSentenceBoundary( aBoundary, aBoundary.startPos - 1 ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + } + break; + case AccessibleTextType::PARAGRAPH: + { + // get paragraph at index + implGetParagraphBoundary( aBoundary, nIndex ); + // get previous paragraph + if ( aBoundary.startPos > 0 ) + { + implGetParagraphBoundary( aBoundary, aBoundary.startPos - 1 ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + } + break; + case AccessibleTextType::LINE: + { + // get line at index + implGetLineBoundary( aBoundary, nIndex ); + // get previous line + if ( aBoundary.startPos > 0 ) + { + implGetLineBoundary( aBoundary, aBoundary.startPos - 1 ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + } + break; + case AccessibleTextType::ATTRIBUTE_RUN: + { + // TODO: implGetAttributeRunBoundary() (incompatible!) + } + break; + default: + { + // unknown text type + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + TextSegment OCommonAccessibleText::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException) + { + ::rtl::OUString sText( implGetText() ); + sal_Int32 nLength = sText.getLength(); + + if ( !implIsValidIndex( nIndex, nLength ) && nIndex != nLength ) + throw IndexOutOfBoundsException(); + + i18n::Boundary aBoundary; + TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch ( aTextType ) + { + case AccessibleTextType::CHARACTER: + { + if ( implIsValidIndex( nIndex + 1, nLength ) ) + { + aResult.SegmentText = sText.copy( nIndex + 1, 1 ); + aResult.SegmentStart = nIndex+1; + aResult.SegmentEnd = nIndex+2; + } + } + break; + case AccessibleTextType::GLYPH: + { + // get glyph at index + implGetGlyphBoundary( aBoundary, nIndex ); + // get next glyph + if ( aBoundary.endPos < nLength ) + { + implGetGlyphBoundary( aBoundary, aBoundary.endPos ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + } + break; + case AccessibleTextType::WORD: + { + // get word at index + implGetWordBoundary( aBoundary, nIndex ); + // get next word + sal_Bool bWord = sal_False; + while ( !bWord && aBoundary.endPos < nLength ) + bWord = implGetWordBoundary( aBoundary, aBoundary.endPos ); + if ( bWord && implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::SENTENCE: + { + // get sentence at index + implGetSentenceBoundary( aBoundary, nIndex ); + // get next sentence + sal_Int32 nEnd = aBoundary.endPos; + sal_Int32 nI = aBoundary.endPos; + sal_Bool bFound = sal_False; + while ( !bFound && ++nI < nLength ) + { + implGetSentenceBoundary( aBoundary, nI ); + bFound = ( aBoundary.endPos > nEnd ); + } + if ( bFound && implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + break; + case AccessibleTextType::PARAGRAPH: + { + // get paragraph at index + implGetParagraphBoundary( aBoundary, nIndex ); + // get next paragraph + if ( aBoundary.endPos < nLength ) + { + implGetParagraphBoundary( aBoundary, aBoundary.endPos ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + } + break; + case AccessibleTextType::LINE: + { + // get line at index + implGetLineBoundary( aBoundary, nIndex ); + // get next line + if ( aBoundary.endPos < nLength ) + { + implGetLineBoundary( aBoundary, aBoundary.endPos ); + if ( implIsValidBoundary( aBoundary, nLength ) ) + { + aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); + aResult.SegmentStart = aBoundary.startPos; + aResult.SegmentEnd = aBoundary.endPos; + } + } + } + break; + case AccessibleTextType::ATTRIBUTE_RUN: + { + // TODO: implGetAttributeRunBoundary() (incompatible!) + } + break; + default: + { + // unknown text type + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + bool OCommonAccessibleText::implInitTextChangedEvent( + const rtl::OUString& rOldString, + const rtl::OUString& rNewString, + ::com::sun::star::uno::Any& rDeleted, + ::com::sun::star::uno::Any& rInserted) // throw() + { + sal_uInt32 nLenOld = rOldString.getLength(); + sal_uInt32 nLenNew = rNewString.getLength(); + + // equal + if ((0 == nLenOld) && (0 == nLenNew)) + return false; + + TextSegment aDeletedText; + TextSegment aInsertedText; + + aDeletedText.SegmentStart = -1; + aDeletedText.SegmentEnd = -1; + aInsertedText.SegmentStart = -1; + aInsertedText.SegmentEnd = -1; + + // insert only + if ((0 == nLenOld) && (nLenNew > 0)) + { + aInsertedText.SegmentStart = 0; + aInsertedText.SegmentEnd = nLenNew; + aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); + + rInserted <<= aInsertedText; + return true; + } + + // delete only + if ((nLenOld > 0) && (0 == nLenNew)) + { + aDeletedText.SegmentStart = 0; + aDeletedText.SegmentEnd = nLenOld; + aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); + + rDeleted <<= aDeletedText; + return true; + } + + const sal_Unicode* pFirstDiffOld = rOldString.getStr(); + const sal_Unicode* pLastDiffOld = rOldString.getStr() + nLenOld; + const sal_Unicode* pFirstDiffNew = rNewString.getStr(); + const sal_Unicode* pLastDiffNew = rNewString.getStr() + nLenNew; + + // find first difference + while ((*pFirstDiffOld == *pFirstDiffNew) && + (pFirstDiffOld < pLastDiffOld) && + (pFirstDiffNew < pLastDiffNew)) + { + pFirstDiffOld++; + pFirstDiffNew++; + } + + // equality test + if ((0 == *pFirstDiffOld) && (0 == *pFirstDiffNew)) + return false; + + // find last difference + while ( ( pLastDiffOld > pFirstDiffOld) && + ( pLastDiffNew > pFirstDiffNew) && + (pLastDiffOld[-1] == pLastDiffNew[-1])) + { + pLastDiffOld--; + pLastDiffNew--; + } + + if (pFirstDiffOld < pLastDiffOld) + { + aDeletedText.SegmentStart = pFirstDiffOld - rOldString.getStr(); + aDeletedText.SegmentEnd = pLastDiffOld - rOldString.getStr(); + aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); + + rDeleted <<= aDeletedText; + } + + if (pFirstDiffNew < pLastDiffNew) + { + aInsertedText.SegmentStart = pFirstDiffNew - rNewString.getStr(); + aInsertedText.SegmentEnd = pLastDiffNew - rNewString.getStr(); + aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); + + rInserted <<= aInsertedText; + } + return true; + } + + //============================================================================== + // OAccessibleTextHelper + //============================================================================== + + OAccessibleTextHelper::OAccessibleTextHelper() + { + } + + // ----------------------------------------------------------------------------- + + OAccessibleTextHelper::OAccessibleTextHelper( IMutex* _pExternalLock ) + :OAccessibleExtendedComponentHelper( _pExternalLock ) + { + } + + // ----------------------------------------------------------------------------- + // XInterface + // ----------------------------------------------------------------------------- + + IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base ) + + // ----------------------------------------------------------------------------- + // XTypeProvider + // ----------------------------------------------------------------------------- + + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base ) + + // ----------------------------------------------------------------------------- + // XAccessibleText + // ----------------------------------------------------------------------------- + + sal_Unicode OAccessibleTextHelper::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getCharacter( nIndex ); + } + + // ----------------------------------------------------------------------------- + + sal_Int32 OAccessibleTextHelper::getCharacterCount() throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getCharacterCount(); + } + + // ----------------------------------------------------------------------------- + + ::rtl::OUString OAccessibleTextHelper::getSelectedText() throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getSelectedText(); + } + + // ----------------------------------------------------------------------------- + + sal_Int32 OAccessibleTextHelper::getSelectionStart() throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getSelectionStart(); + } + + // ----------------------------------------------------------------------------- + + sal_Int32 OAccessibleTextHelper::getSelectionEnd() throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getSelectionEnd(); + } + + // ----------------------------------------------------------------------------- + + ::rtl::OUString OAccessibleTextHelper::getText() throw (RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getText(); + } + + // ----------------------------------------------------------------------------- + + ::rtl::OUString OAccessibleTextHelper::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex ); + } + + // ----------------------------------------------------------------------------- + + TextSegment OAccessibleTextHelper::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType ); + } + + // ----------------------------------------------------------------------------- + + TextSegment OAccessibleTextHelper::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType ); + } + + // ----------------------------------------------------------------------------- + + TextSegment OAccessibleTextHelper::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException) + { + OExternalLockGuard aGuard( this ); + + return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType ); + } + + // ----------------------------------------------------------------------------- + +//.............................................................................. +} // namespace comphelper +//.............................................................................. + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblewrapper.cxx b/comphelper/source/misc/accessiblewrapper.cxx new file mode 100644 index 000000000000..d89fb9080b73 --- /dev/null +++ b/comphelper/source/misc/accessiblewrapper.cxx @@ -0,0 +1,686 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include "comphelper/accessiblewrapper.hxx" +#include <com/sun/star/reflection/XProxyFactory.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> + +#include <algorithm> + +using namespace ::comphelper; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +//............................................................................. +namespace comphelper +{ +//............................................................................. + + //========================================================================= + //= OWrappedAccessibleChildrenManager + //========================================================================= + //-------------------------------------------------------------------- + struct RemoveEventListener + : public ::std::unary_function< AccessibleMap::value_type, void > + { + private: + Reference< XEventListener > m_xListener; + + public: + RemoveEventListener( const Reference< XEventListener >& _rxListener ) + :m_xListener( _rxListener ) + { + } + + void operator()( const AccessibleMap::value_type& _rMapEntry ) const + { + Reference< XComponent > xComp( _rMapEntry.first, UNO_QUERY ); + if ( xComp.is() ) + xComp->removeEventListener( m_xListener ); + } + }; + + //-------------------------------------------------------------------- + struct DisposeMappedChild + : public ::std::unary_function< AccessibleMap::value_type, void > + { + void operator()( const AccessibleMap::value_type& _rMapEntry ) const + { + Reference< XComponent > xContextComponent; + if ( _rMapEntry.second.is() ) + xContextComponent = xContextComponent.query( _rMapEntry.second->getAccessibleContext() ); + if ( xContextComponent.is() ) + xContextComponent->dispose(); + } + }; + + //------------------------------------------------------------------------- + OWrappedAccessibleChildrenManager::OWrappedAccessibleChildrenManager( const Reference< XMultiServiceFactory >& _rxORB ) + :m_xORB( _rxORB ) + ,m_bTransientChildren( sal_True ) + { + } + + //------------------------------------------------------------------------- + OWrappedAccessibleChildrenManager::~OWrappedAccessibleChildrenManager( ) + { + } + + //------------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::setTransientChildren( sal_Bool _bSet ) + { + m_bTransientChildren = _bSet; + } + + //------------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::setOwningAccessible( const Reference< XAccessible >& _rxAcc ) + { + OSL_ENSURE( !m_aOwningAccessible.get().is(), "OWrappedAccessibleChildrenManager::setOwningAccessible: to be called only once!" ); + m_aOwningAccessible = WeakReference< XAccessible >( _rxAcc ); + } + + //------------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::removeFromCache( const Reference< XAccessible >& _rxKey ) + { + AccessibleMap::iterator aRemovedPos = m_aChildrenMap.find( _rxKey ); + if ( m_aChildrenMap.end() != aRemovedPos ) + { // it was cached + // remove ourself as event listener + RemoveEventListener aOperator( this ); + aOperator( *aRemovedPos ); + // and remove the entry from the map + m_aChildrenMap.erase( aRemovedPos ); + } + } + + //------------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::invalidateAll( ) + { + // remove as event listener from the map elements + ::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), RemoveEventListener( this ) ); + // clear the map + AccessibleMap aMap; + m_aChildrenMap.swap( aMap ); + } + + //------------------------------------------------------------------------- + Reference< XAccessible > OWrappedAccessibleChildrenManager::getAccessibleWrapperFor( + const Reference< XAccessible >& _rxKey, sal_Bool _bCreate ) + { + Reference< XAccessible > xValue; + + if( !_rxKey.is() ) + { + // fprintf( stderr, "It was this path that was crashing stuff\n" ); + return xValue; + } + + // do we have this child in the cahce? + AccessibleMap::const_iterator aPos = m_aChildrenMap.find( _rxKey ); + if ( m_aChildrenMap.end() != aPos ) + { + xValue = aPos->second; + } + else if ( _bCreate ) + { // not found in the cache, and allowed to create + // -> new wrapper + xValue = new OAccessibleWrapper( m_xORB, _rxKey, (Reference< XAccessible >)m_aOwningAccessible ); + + // see if we do cache children + if ( !m_bTransientChildren ) + { + if (!m_aChildrenMap.insert( + AccessibleMap::value_type( _rxKey, xValue ) ).second) + { + OSL_ENSURE( + false, + "OWrappedAccessibleChildrenManager::" + "getAccessibleWrapperFor: element was already" + " inserted!" ); + } + + // listen for disposals of inner children - this may happen when the inner context + // is the owner for the inner children (it will dispose these children, and of course + // not our wrapper for these children) + Reference< XComponent > xComp( _rxKey, UNO_QUERY ); + if ( xComp.is() ) + xComp->addEventListener( this ); + } + } + + return xValue; + } + + //------------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::dispose() + { + // dispose our children + ::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), RemoveEventListener( this ) ); + ::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), DisposeMappedChild( ) ); + // clear our children + AccessibleMap aMap; + m_aChildrenMap.swap( aMap ); + } + + //-------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::implTranslateChildEventValue( const Any& _rInValue, Any& _rOutValue ) + { + _rOutValue.clear(); + Reference< XAccessible > xChild; + if ( _rInValue >>= xChild ) + _rOutValue <<= getAccessibleWrapperFor( xChild, sal_True ); + } + + //------------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::translateAccessibleEvent( const AccessibleEventObject& _rEvent, AccessibleEventObject& _rTranslatedEvent ) + { + // just in case we can't translate some of the values: + _rTranslatedEvent.NewValue = _rEvent.NewValue; + _rTranslatedEvent.OldValue = _rEvent.OldValue; + + switch ( _rEvent.EventId ) + { + case AccessibleEventId::CHILD: + case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED: + case AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED: + case AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED: + case AccessibleEventId::LABEL_FOR_RELATION_CHANGED: + case AccessibleEventId::LABELED_BY_RELATION_CHANGED: + case AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED: + case AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED: + // these are events where both the old and the new value contain child references + implTranslateChildEventValue( _rEvent.OldValue, _rTranslatedEvent.OldValue ); + implTranslateChildEventValue( _rEvent.NewValue, _rTranslatedEvent.NewValue ); + break; + + case AccessibleEventId::NAME_CHANGED: + case AccessibleEventId::DESCRIPTION_CHANGED: + case AccessibleEventId::ACTION_CHANGED: + case AccessibleEventId::STATE_CHANGED: + case AccessibleEventId::BOUNDRECT_CHANGED: + case AccessibleEventId::INVALIDATE_ALL_CHILDREN: + case AccessibleEventId::SELECTION_CHANGED: + case AccessibleEventId::VISIBLE_DATA_CHANGED: + case AccessibleEventId::VALUE_CHANGED: + case AccessibleEventId::MEMBER_OF_RELATION_CHANGED: + case AccessibleEventId::CARET_CHANGED: + case AccessibleEventId::TEXT_CHANGED: + case AccessibleEventId::HYPERTEXT_CHANGED: + case AccessibleEventId::TABLE_CAPTION_CHANGED: + case AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED: + case AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED: + case AccessibleEventId::TABLE_MODEL_CHANGED: + case AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED: + case AccessibleEventId::TABLE_ROW_HEADER_CHANGED: + case AccessibleEventId::TABLE_SUMMARY_CHANGED: + // --> PB 2006-03-21 #130798# EventId TEXT_SELECTION_CHANGED was missed + // these Ids are also missed: SUB_WINDOW_OF_RELATION_CHANGED & TEXT_ATTRIBUTE_CHANGED + case AccessibleEventId::TEXT_SELECTION_CHANGED: + // <-- + // nothing to translate + break; + + default: + OSL_ENSURE( sal_False, "OWrappedAccessibleChildrenManager::translateAccessibleEvent: unknown (or unexpected) event id!" ); + break; + } + } + + //------------------------------------------------------------------------- + void OWrappedAccessibleChildrenManager::handleChildNotification( const AccessibleEventObject& _rEvent ) + { + if ( AccessibleEventId::INVALIDATE_ALL_CHILDREN == _rEvent.EventId ) + { // clear our child map + invalidateAll( ); + } + else if ( AccessibleEventId::CHILD == _rEvent.EventId ) + { + // check if the removed or replaced element is cached + Reference< XAccessible > xRemoved; + if ( _rEvent.OldValue >>= xRemoved ) + removeFromCache( xRemoved ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OWrappedAccessibleChildrenManager::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + // this should come from one of the inner XAccessible's of our children + Reference< XAccessible > xSource( _rSource.Source, UNO_QUERY ); + AccessibleMap::iterator aDisposedPos = m_aChildrenMap.find( xSource ); +#if OSL_DEBUG_LEVEL > 0 + if ( m_aChildrenMap.end() == aDisposedPos ) + { + OSL_ENSURE( sal_False, + "OWrappedAccessibleChildrenManager::disposing: where did this come from?" ); + // helper for dignostics + Reference< XAccessible > xOwningAccessible( m_aOwningAccessible ); + Reference< XAccessibleContext > xContext; + try + { + if ( xOwningAccessible.is() ) + xContext = xOwningAccessible->getAccessibleContext(); + if ( xContext.is() ) + { + ::rtl::OUString sName = xContext->getAccessibleName(); + ::rtl::OUString sDescription = xContext->getAccessibleDescription(); +// sal_Int32 nPlaceYourBreakpointHere = 0; + } + } + catch( const Exception& /*e*/ ) + { + // silent this, it's only diagnostics which failed + } + } +#endif + if ( m_aChildrenMap.end() != aDisposedPos ) + { + m_aChildrenMap.erase( aDisposedPos ); + } + } + + //========================================================================= + //= OAccessibleWrapper (implementation) + //========================================================================= + //------------------------------------------------------------------------- + OAccessibleWrapper::OAccessibleWrapper( const Reference< XMultiServiceFactory >& _rxORB, + const Reference< XAccessible >& _rxInnerAccessible, const Reference< XAccessible >& _rxParentAccessible ) + :OAccessibleWrapper_Base( ) + ,OComponentProxyAggregation( _rxORB, Reference< XComponent >( _rxInnerAccessible, UNO_QUERY ) ) + ,m_xParentAccessible( _rxParentAccessible ) + ,m_xInnerAccessible( _rxInnerAccessible ) + { + } + + //-------------------------------------------------------------------- + OAccessibleWrapper::~OAccessibleWrapper( ) + { + if ( !m_rBHelper.bDisposed ) + { + acquire(); // to prevent duplicate dtor calls + dispose(); + } + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleWrapper, OComponentProxyAggregation, OAccessibleWrapper_Base ) + IMPLEMENT_FORWARD_REFCOUNT( OAccessibleWrapper, OComponentProxyAggregation ) + + //-------------------------------------------------------------------- + Any OAccessibleWrapper::queryInterface( const Type& _rType ) throw (RuntimeException) + { + // #111089# instead of the inner XAccessible the proxy XAccessible must be returned + Any aReturn = OAccessibleWrapper_Base::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OComponentProxyAggregation::queryInterface( _rType ); + + return aReturn; + } + + //-------------------------------------------------------------------- + Reference< XAccessibleContext > OAccessibleWrapper::getContextNoCreate( ) const + { + return (Reference< XAccessibleContext >)m_aContext; + } + + //-------------------------------------------------------------------- + OAccessibleContextWrapper* OAccessibleWrapper::createAccessibleContext( const Reference< XAccessibleContext >& _rxInnerContext ) + { + return new OAccessibleContextWrapper( getORB(), _rxInnerContext, this, m_xParentAccessible ); + } + + //-------------------------------------------------------------------- + Reference< XAccessibleContext > SAL_CALL OAccessibleWrapper::getAccessibleContext( ) throw (RuntimeException) + { + // see if the context is still alive (we cache it) + Reference< XAccessibleContext > xContext = (Reference< XAccessibleContext >)m_aContext; + if ( !xContext.is() ) + { + // create a new context + Reference< XAccessibleContext > xInnerContext = m_xInnerAccessible->getAccessibleContext( ); + if ( xInnerContext.is() ) + { + xContext = createAccessibleContext( xInnerContext ); + // cache it + m_aContext = WeakReference< XAccessibleContext >( xContext ); + } + } + + return xContext; + } + + //========================================================================= + //= OAccessibleWrapper (implementation) + //========================================================================= + //------------------------------------------------------------------------- + OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper( + const Reference< XMultiServiceFactory >& _rxORB, + ::cppu::OBroadcastHelper& _rBHelper, + const Reference< XAccessibleContext >& _rxInnerAccessibleContext, + const Reference< XAccessible >& _rxOwningAccessible, + const Reference< XAccessible >& _rxParentAccessible ) + :OComponentProxyAggregationHelper( _rxORB, _rBHelper ) + ,m_xInnerContext( _rxInnerAccessibleContext ) + ,m_xOwningAccessible( _rxOwningAccessible ) + ,m_xParentAccessible( _rxParentAccessible ) + ,m_pChildMapper( NULL ) + { + // initialize the mapper for our children + m_pChildMapper = new OWrappedAccessibleChildrenManager( getORB() ); + m_pChildMapper->acquire(); + + // determine if we're allowed to cache children + Reference< XAccessibleStateSet > xStates( m_xInnerContext->getAccessibleStateSet( ) ); + OSL_ENSURE( xStates.is(), "OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper: no inner state set!" ); + m_pChildMapper->setTransientChildren( !xStates.is() || xStates->contains( AccessibleStateType::MANAGES_DESCENDANTS) ); + + m_pChildMapper->setOwningAccessible( m_xOwningAccessible ); + } + + //-------------------------------------------------------------------- + void OAccessibleContextWrapperHelper::aggregateProxy( oslInterlockedCount& _rRefCount, ::cppu::OWeakObject& _rDelegator ) + { + Reference< XComponent > xInnerComponent( m_xInnerContext, UNO_QUERY ); + OSL_ENSURE( xInnerComponent.is(), "OComponentProxyAggregation::aggregateProxy: accessible is no XComponent!" ); + if ( xInnerComponent.is() ) + componentAggregateProxyFor( xInnerComponent, _rRefCount, _rDelegator ); + + // add as event listener to the inner context, because we want to multiplex the AccessibleEvents + osl_incrementInterlockedCount( &_rRefCount ); + { + Reference< XAccessibleEventBroadcaster > xBroadcaster( m_xInner, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->addEventListener( this ); + } + osl_decrementInterlockedCount( &_rRefCount ); + } + + //-------------------------------------------------------------------- + OAccessibleContextWrapperHelper::~OAccessibleContextWrapperHelper( ) + { + OSL_ENSURE( m_rBHelper.bDisposed, "OAccessibleContextWrapperHelper::~OAccessibleContextWrapperHelper: you should ensure (in your dtor) that the object is disposed!" ); + + m_pChildMapper->release(); + m_pChildMapper = NULL; + } + + //-------------------------------------------------------------------- + Any SAL_CALL OAccessibleContextWrapperHelper::queryInterface( const Type& _rType ) throw (RuntimeException) + { + Any aReturn = OComponentProxyAggregationHelper::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = OAccessibleContextWrapperHelper_Base::queryInterface( _rType ); + return aReturn; + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapperHelper, OComponentProxyAggregationHelper, OAccessibleContextWrapperHelper_Base ) + + //-------------------------------------------------------------------- + sal_Int32 SAL_CALL OAccessibleContextWrapperHelper::getAccessibleChildCount( ) throw (RuntimeException) + { + return m_xInnerContext->getAccessibleChildCount(); + } + + //-------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OAccessibleContextWrapperHelper::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException) + { + // get the child of the wrapped component + Reference< XAccessible > xInnerChild = m_xInnerContext->getAccessibleChild( i ); + return m_pChildMapper->getAccessibleWrapperFor( xInnerChild ); + } + + //-------------------------------------------------------------------- + Reference< XAccessibleRelationSet > SAL_CALL OAccessibleContextWrapperHelper::getAccessibleRelationSet( ) throw (RuntimeException) + { + return m_xInnerContext->getAccessibleRelationSet(); + // TODO: if this relation set would contain relations to siblings, we would normally need + // to wrap them, too .... + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleContextWrapperHelper::notifyEvent( const AccessibleEventObject& _rEvent ) throw (RuntimeException) + { +#if OSL_DEBUG_LEVEL > 0 + if ( AccessibleEventId::STATE_CHANGED == _rEvent.EventId ) + { + sal_Bool bChildTransienceChanged = sal_False; + sal_Int16 nChangeState = 0; + if ( _rEvent.OldValue >>= nChangeState ) + bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState; + if ( _rEvent.NewValue >>= nChangeState ) + bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState; + OSL_ENSURE( !bChildTransienceChanged, "OAccessibleContextWrapperHelper::notifyEvent: MANAGES_DESCENDANTS is not expected to change during runtime!" ); + // if this asserts, then we would need to update our m_bTransientChildren flag here, + // as well as (potentially) our child cache + } +#endif + AccessibleEventObject aTranslatedEvent( _rEvent ); + + { + ::osl::MutexGuard aGuard( m_rBHelper.rMutex ); + + // translate the event + queryInterface( ::getCppuType( static_cast< Reference< XInterface >* >( NULL ) ) ) >>= aTranslatedEvent.Source; + m_pChildMapper->translateAccessibleEvent( _rEvent, aTranslatedEvent ); + + // see if any of these notifications affect our child manager + m_pChildMapper->handleChildNotification( _rEvent ); + + if ( aTranslatedEvent.NewValue == m_xInner ) + aTranslatedEvent.NewValue = makeAny(aTranslatedEvent.Source); + if ( aTranslatedEvent.OldValue == m_xInner ) + aTranslatedEvent.OldValue = makeAny(aTranslatedEvent.Source); + } + + notifyTranslatedEvent( aTranslatedEvent ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleContextWrapperHelper::dispose() throw( RuntimeException ) + { + ::osl::MutexGuard aGuard( m_rBHelper.rMutex ); + + // stop multiplexing events + Reference< XAccessibleEventBroadcaster > xBroadcaster( m_xInner, UNO_QUERY ); + OSL_ENSURE( xBroadcaster.is(), "OAccessibleContextWrapperHelper::disposing(): inner context is no broadcaster!" ); + if ( xBroadcaster.is() ) + xBroadcaster->removeEventListener( this ); + + // dispose the child cache/map + m_pChildMapper->dispose(); + + // let the base class dispose the inner component + OComponentProxyAggregationHelper::dispose(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleContextWrapperHelper::disposing( const EventObject& _rEvent ) throw (RuntimeException) + { + // simply disambiguate this + OComponentProxyAggregationHelper::disposing( _rEvent ); + } + + //==================================================================== + //= OAccessibleContextWrapper + //==================================================================== + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleContextWrapper, OAccessibleContextWrapper_CBase, OAccessibleContextWrapperHelper ) + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapper, OAccessibleContextWrapper_CBase, OAccessibleContextWrapperHelper ) + + //-------------------------------------------------------------------- + OAccessibleContextWrapper::OAccessibleContextWrapper( const Reference< XMultiServiceFactory >& _rxORB, + const Reference< XAccessibleContext >& _rxInnerAccessibleContext, const Reference< XAccessible >& _rxOwningAccessible, + const Reference< XAccessible >& _rxParentAccessible ) + :OAccessibleContextWrapper_CBase( m_aMutex ) + ,OAccessibleContextWrapperHelper( _rxORB, rBHelper, _rxInnerAccessibleContext, _rxOwningAccessible, _rxParentAccessible ) + ,m_nNotifierClient( 0 ) + { + aggregateProxy( m_refCount, *this ); + } + + //-------------------------------------------------------------------- + OAccessibleContextWrapper::~OAccessibleContextWrapper() + { + } + + //-------------------------------------------------------------------- + sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleChildCount( ) throw (RuntimeException) + { + return OAccessibleContextWrapperHelper::getAccessibleChildCount(); + } + + //-------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException) + { + return OAccessibleContextWrapperHelper::getAccessibleChild( i ); + } + + //-------------------------------------------------------------------- + Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleParent( ) throw (RuntimeException) + { + return m_xParentAccessible; + } + + //-------------------------------------------------------------------- + sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent( ) throw (RuntimeException) + { + return m_xInnerContext->getAccessibleIndexInParent(); + } + + //-------------------------------------------------------------------- + sal_Int16 SAL_CALL OAccessibleContextWrapper::getAccessibleRole( ) throw (RuntimeException) + { + return m_xInnerContext->getAccessibleRole(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OAccessibleContextWrapper::getAccessibleDescription( ) throw (RuntimeException) + { + return m_xInnerContext->getAccessibleDescription(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OAccessibleContextWrapper::getAccessibleName( ) throw (RuntimeException) + { + return m_xInnerContext->getAccessibleName(); + } + + //-------------------------------------------------------------------- + Reference< XAccessibleRelationSet > SAL_CALL OAccessibleContextWrapper::getAccessibleRelationSet( ) throw (RuntimeException) + { + return OAccessibleContextWrapperHelper::getAccessibleRelationSet(); + } + + //-------------------------------------------------------------------- + Reference< XAccessibleStateSet > SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet( ) throw (RuntimeException) + { + return m_xInnerContext->getAccessibleStateSet(); + } + + //-------------------------------------------------------------------- + Locale SAL_CALL OAccessibleContextWrapper::getLocale( ) throw (IllegalAccessibleComponentStateException, RuntimeException) + { + return m_xInnerContext->getLocale(); + } + + //-------------------------------------------------------------------- + void OAccessibleContextWrapper::notifyTranslatedEvent( const AccessibleEventObject& _rEvent ) throw (RuntimeException) + { + if ( m_nNotifierClient ) + AccessibleEventNotifier::addEvent( m_nNotifierClient, _rEvent ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleContextWrapper::addEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_nNotifierClient ) + m_nNotifierClient = AccessibleEventNotifier::registerClient( ); + AccessibleEventNotifier::addEventListener( m_nNotifierClient, _rxListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleContextWrapper::removeEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_nNotifierClient ) + { + if ( 0 == AccessibleEventNotifier::removeEventListener( m_nNotifierClient, _rxListener ) ) + { + AccessibleEventNotifier::TClientId nId( m_nNotifierClient ); + m_nNotifierClient = 0; + AccessibleEventNotifier::revokeClient( nId ); + } + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleContextWrapper::disposing() throw (RuntimeException) + { + AccessibleEventNotifier::TClientId nClientId( 0 ); + + // --- <mutex lock> ----------------------------------------- + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // prepare notifying our AccessibleListeners + if ( m_nNotifierClient ) + { + nClientId = m_nNotifierClient; + m_nNotifierClient = 0; + } + } + // --- </mutex lock> ----------------------------------------- + + // let the base class do + OAccessibleContextWrapperHelper::dispose(); + + // notify the disposal + if ( nClientId ) + AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OAccessibleContextWrapper::dispose() throw( RuntimeException ) + { + // simply disambiguate + OComponentProxyAggregation_CBase::dispose(); + } + +//............................................................................. +} // namespace accessibility +//............................................................................. + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accimplaccess.cxx b/comphelper/source/misc/accimplaccess.cxx new file mode 100644 index 000000000000..45b9edaf9ed5 --- /dev/null +++ b/comphelper/source/misc/accimplaccess.cxx @@ -0,0 +1,191 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/accimplaccess.hxx> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <cppuhelper/typeprovider.hxx> + +#include <set> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + +#define BITFIELDSIZE ( sizeof( sal_Int64 ) * 8 ) + // maximum number of bits we have in a sal_Int64 + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::lang::XUnoTunnel; + using ::com::sun::star::accessibility::XAccessible; + using ::com::sun::star::accessibility::XAccessibleContext; + + //===================================================================== + //= OAccImpl_Impl + //===================================================================== + struct OAccImpl_Impl + { + Reference< XAccessible > m_xAccParent; + sal_Int64 m_nForeignControlledStates; + }; + + + //===================================================================== + //= OAccessibleImplementationAccess + //===================================================================== + //--------------------------------------------------------------------- + OAccessibleImplementationAccess::OAccessibleImplementationAccess( ) + :m_pImpl( new OAccImpl_Impl ) + { + } + + //--------------------------------------------------------------------- + OAccessibleImplementationAccess::~OAccessibleImplementationAccess( ) + { + delete m_pImpl; + m_pImpl = NULL; + } + + //--------------------------------------------------------------------- + Reference< XAccessible > OAccessibleImplementationAccess::implGetForeignControlledParent( ) const + { + return m_pImpl->m_xAccParent; + } + + //--------------------------------------------------------------------- + void OAccessibleImplementationAccess::setAccessibleParent( const Reference< XAccessible >& _rxAccParent ) + { + m_pImpl->m_xAccParent = _rxAccParent; + } + + //--------------------------------------------------------------------- + sal_Int64 OAccessibleImplementationAccess::implGetForeignControlledStates( ) const + { + return m_pImpl->m_nForeignControlledStates; + } + + //--------------------------------------------------------------------- + void OAccessibleImplementationAccess::setStateBit( const sal_Int16 _nState, const sal_Bool _bSet ) + { + OSL_ENSURE( _nState >= 0 && static_cast< sal_uInt16 >(_nState) < BITFIELDSIZE, "OAccessibleImplementationAccess::setStateBit: no more bits (shutting down the universe now)!" ); + + sal_uInt64 nBitMask( 1 ); + nBitMask <<= _nState; + if ( _bSet ) + m_pImpl->m_nForeignControlledStates |= nBitMask; + else + m_pImpl->m_nForeignControlledStates &= ~nBitMask; + } + + //--------------------------------------------------------------------- + sal_Bool OAccessibleImplementationAccess::setForeignControlledState( const Reference< XAccessibleContext >& _rxComponent, const sal_Int16 _nState, + const sal_Bool _bSet ) + { + OAccessibleImplementationAccess* pImplementation = getImplementation( _rxComponent ); + + if ( pImplementation ) + pImplementation->setStateBit( _nState, _bSet ); + + return ( NULL != pImplementation ); + } + + //--------------------------------------------------------------------- + const Sequence< sal_Int8 >& OAccessibleImplementationAccess::getUnoTunnelImplementationId() + { + static Sequence< sal_Int8 > aId; + if ( !aId.getLength() ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !aId.getLength() ) + { + static ::cppu::OImplementationId aImplId; + // unfortunately, the OImplementationId::getImplementationId returns a copy, not a static reference ... + aId = aImplId.getImplementationId(); + } + } + return aId; + } + + //--------------------------------------------------------------------- + sal_Int64 SAL_CALL OAccessibleImplementationAccess::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw (RuntimeException) + { + sal_Int64 nReturn( 0 ); + + if ( ( _rIdentifier.getLength() == 16 ) + && ( 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ) ) + ) + nReturn = reinterpret_cast< sal_Int64 >( this ); + + return nReturn; + } + + //--------------------------------------------------------------------- + OAccessibleImplementationAccess* OAccessibleImplementationAccess::getImplementation( const Reference< XAccessibleContext >& _rxComponent ) + { + OAccessibleImplementationAccess* pImplementation = NULL; + try + { + Reference< XUnoTunnel > xTunnel( _rxComponent, UNO_QUERY ); + if ( xTunnel.is() ) + { + pImplementation = reinterpret_cast< OAccessibleImplementationAccess* >( + xTunnel->getSomething( getUnoTunnelImplementationId() ) ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OAccessibleImplementationAccess::setAccessibleParent: caught an exception while retrieving the implementation!" ); + } + return pImplementation; + } + + //--------------------------------------------------------------------- + sal_Bool OAccessibleImplementationAccess::setAccessibleParent( + const Reference< XAccessibleContext >& _rxComponent, const Reference< XAccessible >& _rxNewParent ) + { + OAccessibleImplementationAccess* pImplementation = getImplementation( _rxComponent ); + + if ( pImplementation ) + pImplementation->setAccessibleParent( _rxNewParent ); + + return ( NULL != pImplementation ); + } + +//......................................................................... +} // namespace comphelper +//......................................................................... + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/anytostring.cxx b/comphelper/source/misc/anytostring.cxx new file mode 100644 index 000000000000..306891b74cd9 --- /dev/null +++ b/comphelper/source/misc/anytostring.cxx @@ -0,0 +1,337 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/anytostring.hxx" +#include "osl/diagnose.h" +#include "rtl/ustrbuf.hxx" +#include "typelib/typedescription.h" +#include "com/sun/star/lang/XServiceInfo.hpp" + +using namespace ::com::sun::star; + +namespace comphelper { +namespace { + +void appendTypeError( + rtl::OUStringBuffer & buf, typelib_TypeDescriptionReference * typeRef ) +{ + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("<cannot get type description of type ") ); + buf.append( rtl::OUString::unacquired( &typeRef->pTypeName ) ); + buf.append( static_cast< sal_Unicode >('>') ); +} + +inline void appendChar( rtl::OUStringBuffer & buf, sal_Unicode c ) +{ + if (c < ' ' || c > '~') { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\X") ); + rtl::OUString const s( + rtl::OUString::valueOf( static_cast< sal_Int32 >(c), 16 ) ); + for ( sal_Int32 f = 4 - s.getLength(); f > 0; --f ) + buf.append( static_cast< sal_Unicode >('0') ); + buf.append( s ); + } + else { + buf.append( c ); + } +} + +//------------------------------------------------------------------------------ +void appendValue( rtl::OUStringBuffer & buf, + void const * val, typelib_TypeDescriptionReference * typeRef, + bool prependType ) +{ + if (typeRef->eTypeClass == typelib_TypeClass_VOID) { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("void") ); + return; + } + OSL_ASSERT( val != 0 ); + + if (prependType && + typeRef->eTypeClass != typelib_TypeClass_STRING && + typeRef->eTypeClass != typelib_TypeClass_CHAR && + typeRef->eTypeClass != typelib_TypeClass_BOOLEAN) + { + buf.append( static_cast< sal_Unicode >('(') ); + buf.append( rtl::OUString::unacquired( &typeRef->pTypeName ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(") ") ); + } + + switch (typeRef->eTypeClass) { + case typelib_TypeClass_INTERFACE: { + buf.append( static_cast<sal_Unicode>('@') ); + buf.append( reinterpret_cast< sal_Int64 >( + *static_cast< void * const * >(val) ), 16 ); + uno::Reference< lang::XServiceInfo > xServiceInfo( + *static_cast< uno::XInterface * const * >(val), + uno::UNO_QUERY ); + if (xServiceInfo.is()) { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + " (ImplementationName = \"") ); + buf.append( xServiceInfo->getImplementationName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); + } + break; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); + typelib_TypeDescription * typeDescr = 0; + typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); + if (typeDescr == 0 || !typelib_typedescription_complete( &typeDescr )) { + appendTypeError( buf, typeRef ); + } + else { + typelib_CompoundTypeDescription * compType = + reinterpret_cast< typelib_CompoundTypeDescription * >( + typeDescr ); + sal_Int32 nDescr = compType->nMembers; + + if (compType->pBaseTypeDescription) { + appendValue( + buf, val, reinterpret_cast< + typelib_TypeDescription * >( + compType->pBaseTypeDescription)->pWeakRef, false ); + if (nDescr > 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + } + + typelib_TypeDescriptionReference ** ppTypeRefs = + compType->ppTypeRefs; + sal_Int32 * memberOffsets = compType->pMemberOffsets; + rtl_uString ** ppMemberNames = compType->ppMemberNames; + + for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) + { + buf.append( ppMemberNames[ nPos ] ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") ); + typelib_TypeDescription * memberType = 0; + TYPELIB_DANGER_GET( &memberType, ppTypeRefs[ nPos ] ); + if (memberType == 0) { + appendTypeError( buf, ppTypeRefs[ nPos ] ); + } + else { + appendValue( buf, + static_cast< char const * >( + val ) + memberOffsets[ nPos ], + memberType->pWeakRef, true ); + TYPELIB_DANGER_RELEASE( memberType ); + } + if (nPos < (nDescr - 1)) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + } + } + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); + if (typeDescr != 0) + typelib_typedescription_release( typeDescr ); + break; + } + case typelib_TypeClass_SEQUENCE: { + typelib_TypeDescription * typeDescr = 0; + TYPELIB_DANGER_GET( &typeDescr, typeRef ); + if (typeDescr == 0) { + appendTypeError( buf,typeRef ); + } + else { + typelib_TypeDescriptionReference * elementTypeRef = + reinterpret_cast< + typelib_IndirectTypeDescription * >(typeDescr)->pType; + typelib_TypeDescription * elementTypeDescr = 0; + TYPELIB_DANGER_GET( &elementTypeDescr, elementTypeRef ); + if (elementTypeDescr == 0) + { + appendTypeError( buf, elementTypeRef ); + } + else + { + sal_Int32 nElementSize = elementTypeDescr->nSize; + uno_Sequence * seq = + *static_cast< uno_Sequence * const * >(val); + sal_Int32 nElements = seq->nElements; + + if (nElements > 0) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); + char const * pElements = seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + appendValue( + buf, pElements + (nElementSize * nPos), + elementTypeDescr->pWeakRef, false ); + if (nPos < (nElements - 1)) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + } + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); + } + else + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") ); + } + TYPELIB_DANGER_RELEASE( elementTypeDescr ); + } + TYPELIB_DANGER_RELEASE( typeDescr ); + } + break; + } + case typelib_TypeClass_ANY: { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); + uno_Any const * pAny = static_cast< uno_Any const * >(val); + appendValue( buf, pAny->pData, pAny->pType, true ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); + break; + } + case typelib_TypeClass_TYPE: + buf.append( (*reinterpret_cast< + typelib_TypeDescriptionReference * const * >(val) + )->pTypeName ); + break; + case typelib_TypeClass_STRING: { + buf.append( static_cast< sal_Unicode >('\"') ); + rtl::OUString const & str = rtl::OUString::unacquired( + static_cast< rtl_uString * const * >(val) ); + sal_Int32 len = str.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + sal_Unicode c = str[ pos ]; + if (c == '\"') + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\"") ); + else if (c == '\\') + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\\") ); + else + appendChar( buf, c ); + } + buf.append( static_cast< sal_Unicode >('\"') ); + break; + } + case typelib_TypeClass_ENUM: { + typelib_TypeDescription * typeDescr = 0; + typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); + if (typeDescr == 0 || !typelib_typedescription_complete( &typeDescr )) { + appendTypeError( buf, typeRef ); + } + else + { + sal_Int32 * pValues = + reinterpret_cast< typelib_EnumTypeDescription * >( + typeDescr )->pEnumValues; + sal_Int32 nPos = reinterpret_cast< typelib_EnumTypeDescription * >( + typeDescr )->nEnumValues; + while (nPos--) + { + if (pValues[ nPos ] == *static_cast< int const * >(val)) + break; + } + if (nPos >= 0) + { + buf.append( reinterpret_cast< typelib_EnumTypeDescription * >( + typeDescr )->ppEnumNames[ nPos ] ); + } + else + { + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("?unknown enum value?") ); + } + } + if (typeDescr != 0) + typelib_typedescription_release( typeDescr ); + break; + } + case typelib_TypeClass_BOOLEAN: + if (*static_cast< sal_Bool const * >(val) != sal_False) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") ); + else + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") ); + break; + case typelib_TypeClass_CHAR: { + buf.append( static_cast< sal_Unicode >('\'') ); + sal_Unicode c = *static_cast< sal_Unicode const * >(val); + if (c == '\'') + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\'") ); + else if (c == '\\') + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\\") ); + else + appendChar( buf, c ); + buf.append( static_cast< sal_Unicode >('\'') ); + break; + } + case typelib_TypeClass_FLOAT: + buf.append( *static_cast< float const * >(val) ); + break; + case typelib_TypeClass_DOUBLE: + buf.append( *static_cast< double const * >(val) ); + break; + case typelib_TypeClass_BYTE: + buf.append( static_cast< sal_Int32 >( + *static_cast< sal_Int8 const * >(val) ) ); + break; + case typelib_TypeClass_SHORT: + buf.append( static_cast< sal_Int32 >( + *static_cast< sal_Int16 const * >(val) ) ); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + buf.append( static_cast< sal_Int32 >( + *static_cast< sal_uInt16 const * >(val) ) ); + break; + case typelib_TypeClass_LONG: + buf.append( *static_cast< sal_Int32 const * >(val) ); + break; + case typelib_TypeClass_UNSIGNED_LONG: + buf.append( static_cast< sal_Int64 >( + *static_cast< sal_uInt32 const * >(val) ) ); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + buf.append( *static_cast< sal_Int64 const * >(val) ); + break; +// case typelib_TypeClass_UNION: +// case typelib_TypeClass_ARRAY: +// case typelib_TypeClass_UNKNOWN: +// case typelib_TypeClass_SERVICE: +// case typelib_TypeClass_MODULE: + default: + buf.append( static_cast< sal_Unicode >('?') ); + break; + } +} + +} // anon namespace + +//============================================================================== +rtl::OUString anyToString( uno::Any const & value ) +{ + rtl::OUStringBuffer buf; + appendValue( buf, value.getValue(), value.getValueTypeRef(), true ); + return buf.makeStringAndClear(); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/asyncnotification.cxx b/comphelper/source/misc/asyncnotification.cxx new file mode 100644 index 000000000000..f68fda46b9b3 --- /dev/null +++ b/comphelper/source/misc/asyncnotification.cxx @@ -0,0 +1,283 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/asyncnotification.hxx> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <osl/conditn.hxx> +#include <comphelper/guarding.hxx> + +#include <deque> +#include <set> +#include <functional> +#include <algorithm> + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + //==================================================================== + //= AnyEvent + //==================================================================== + //-------------------------------------------------------------------- + AnyEvent::AnyEvent() + :m_refCount( 0 ) + { + } + + //-------------------------------------------------------------------- + AnyEvent::~AnyEvent() + { + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AnyEvent::acquire() + { + return osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AnyEvent::release() + { + if ( 0 == osl_decrementInterlockedCount( &m_refCount ) ) + { + delete this; + return 0; + } + return m_refCount; + } + + //==================================================================== + //= ProcessableEvent + //==================================================================== + struct ProcessableEvent + { + AnyEventRef aEvent; + ::rtl::Reference< IEventProcessor > xProcessor; + + ProcessableEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) + :aEvent( _rEvent ) + ,xProcessor( _xProcessor ) + { + } + + ProcessableEvent( const ProcessableEvent& _rRHS ) + :aEvent( _rRHS.aEvent ) + ,xProcessor( _rRHS.xProcessor ) + { + } + + ProcessableEvent& operator=( const ProcessableEvent& _rRHS ) + { + aEvent = _rRHS.aEvent; + xProcessor = _rRHS.xProcessor; + return *this; + } + }; + + //==================================================================== + typedef ::std::deque< ProcessableEvent > EventQueue; + + //==================================================================== + struct EqualProcessor : public ::std::unary_function< ProcessableEvent, bool > + { + const ::rtl::Reference< IEventProcessor >& rProcessor; + EqualProcessor( const ::rtl::Reference< IEventProcessor >& _rProcessor ) :rProcessor( _rProcessor ) { } + + bool operator()( const ProcessableEvent& _rEvent ) + { + return _rEvent.xProcessor.get() == rProcessor.get(); + } + }; + + //==================================================================== + //= EventNotifierImpl + //==================================================================== + struct EventNotifierImpl + { + ::osl::Mutex aMutex; + oslInterlockedCount m_refCount; + ::osl::Condition aPendingActions; + EventQueue aEvents; + ::std::set< ::rtl::Reference< IEventProcessor > > + m_aDeadProcessors; + + EventNotifierImpl() + :m_refCount( 0 ) + { + } + + private: + EventNotifierImpl( const EventNotifierImpl& ); // never implemented + EventNotifierImpl& operator=( const EventNotifierImpl& ); // never implemented + }; + + //==================================================================== + //= AsyncEventNotifier + //==================================================================== + //-------------------------------------------------------------------- + AsyncEventNotifier::AsyncEventNotifier() + :m_pImpl( new EventNotifierImpl ) + { + } + + //-------------------------------------------------------------------- + AsyncEventNotifier::~AsyncEventNotifier() + { + } + + //-------------------------------------------------------------------- + void AsyncEventNotifier::removeEventsForProcessor( const ::rtl::Reference< IEventProcessor >& _xProcessor ) + { + ::osl::MutexGuard aGuard( m_pImpl->aMutex ); + + // remove all events for this processor + ::std::remove_if( m_pImpl->aEvents.begin(), m_pImpl->aEvents.end(), EqualProcessor( _xProcessor ) ); + + // and just in case that an event for exactly this processor has just been + // popped from the queue, but not yet processed: remember it: + m_pImpl->m_aDeadProcessors.insert( _xProcessor ); + } + + //-------------------------------------------------------------------- + void SAL_CALL AsyncEventNotifier::terminate() + { + ::osl::MutexGuard aGuard( m_pImpl->aMutex ); + + // remember the termination request + AsyncEventNotifier_TBASE::terminate(); + + // awake the thread + m_pImpl->aPendingActions.set(); + } + + //-------------------------------------------------------------------- + void AsyncEventNotifier::addEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) + { + ::osl::MutexGuard aGuard( m_pImpl->aMutex ); + + OSL_TRACE( "AsyncEventNotifier(%p): adding %p\n", this, _rEvent.get() ); + // remember this event + m_pImpl->aEvents.push_back( ProcessableEvent( _rEvent, _xProcessor ) ); + + // awake the thread + m_pImpl->aPendingActions.set(); + } + + //-------------------------------------------------------------------- + void AsyncEventNotifier::run() + { + acquire(); + + // keep us alive, in case we're terminated in the mid of the following + ::rtl::Reference< AsyncEventNotifier > xKeepAlive( this ); + + do + { + AnyEventRef aNextEvent; + ::rtl::Reference< IEventProcessor > xNextProcessor; + + ::osl::ClearableMutexGuard aGuard( m_pImpl->aMutex ); + while ( m_pImpl->aEvents.size() > 0 ) + { + ProcessableEvent aEvent( m_pImpl->aEvents.front() ); + aNextEvent = aEvent.aEvent; + xNextProcessor = aEvent.xProcessor; + m_pImpl->aEvents.pop_front(); + + OSL_TRACE( "AsyncEventNotifier(%p): popping %p\n", this, aNextEvent.get() ); + + if ( !aNextEvent.get() ) + continue; + + // process the event, but only if it's processor did not die inbetween + ::std::set< ::rtl::Reference< IEventProcessor > >::iterator deadPos = m_pImpl->m_aDeadProcessors.find( xNextProcessor ); + if ( deadPos != m_pImpl->m_aDeadProcessors.end() ) + { + m_pImpl->m_aDeadProcessors.erase( xNextProcessor ); + xNextProcessor.clear(); + OSL_TRACE( "AsyncEventNotifier(%p): removing %p\n", this, aNextEvent.get() ); + } + + // if there was a termination request (->terminate), respect it + if ( !schedule() ) + return; + + { + ::comphelper::MutexRelease aReleaseOnce( m_pImpl->aMutex ); + if ( xNextProcessor.get() ) + xNextProcessor->processEvent( *aNextEvent.get() ); + } + } + + // if there was a termination request (->terminate), respect it + if ( !schedule() ) + return; + + // wait for new events to process + aGuard.clear(); + m_pImpl->aPendingActions.reset(); + m_pImpl->aPendingActions.wait(); + } + while ( sal_True ); + } + + //-------------------------------------------------------------------- + void SAL_CALL AsyncEventNotifier::onTerminated() + { + AsyncEventNotifier_TBASE::onTerminated(); + // when we were started (->run), we aquired ourself. Release this now + // that we were finally terminated + release(); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AsyncEventNotifier::acquire() + { + return osl_incrementInterlockedCount( &m_pImpl->m_refCount ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL AsyncEventNotifier::release() + { + if ( 0 == osl_decrementInterlockedCount( &m_pImpl->m_refCount ) ) + { + delete this; + return 0; + } + return m_pImpl->m_refCount; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/comphelper_module.cxx b/comphelper/source/misc/comphelper_module.cxx new file mode 100644 index 000000000000..2ac0fc7e262b --- /dev/null +++ b/comphelper/source/misc/comphelper_module.cxx @@ -0,0 +1,44 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper_module.hxx" + +//........................................................................ +namespace comphelper { namespace module +{ +//........................................................................ + + IMPLEMENT_COMPONENT_MODULE( ComphelperModule ); + +//........................................................................ +} } // namespace comphelper::module +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/comphelper_services.cxx b/comphelper/source/misc/comphelper_services.cxx new file mode 100644 index 000000000000..74c29f7bd4e6 --- /dev/null +++ b/comphelper/source/misc/comphelper_services.cxx @@ -0,0 +1,82 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper_module.hxx" + +//-------------------------------------------------------------------- +extern void createRegistryInfo_OPropertyBag(); +extern void createRegistryInfo_SequenceOutputStream(); +extern void createRegistryInfo_SequenceInputStream(); +extern void createRegistryInfo_UNOMemoryStream(); +extern void createRegistryInfo_IndexedPropertyValuesContainer(); +extern void createRegistryInfo_NamedPropertyValuesContainer(); +extern void createRegistryInfo_AnyCompareFactory(); +extern void createRegistryInfo_OfficeInstallationDirectories(); +extern void createRegistryInfo_OInstanceLocker(); +extern void createRegistryInfo_Map(); +extern void createRegistryInfo_OSimpleLogRing(); +extern void createRegistryInfo_OOfficeRestartManager(); + +//........................................................................ +namespace comphelper { namespace module +{ +//........................................................................ + + static void initializeModule() + { + static bool bInitialized( false ); + if ( !bInitialized ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !bInitialized ) + { + createRegistryInfo_OPropertyBag(); + createRegistryInfo_SequenceOutputStream(); + createRegistryInfo_SequenceInputStream(); + createRegistryInfo_UNOMemoryStream(); + createRegistryInfo_IndexedPropertyValuesContainer(); + createRegistryInfo_NamedPropertyValuesContainer(); + createRegistryInfo_AnyCompareFactory(); + createRegistryInfo_OfficeInstallationDirectories(); + createRegistryInfo_OInstanceLocker(); + createRegistryInfo_Map(); + createRegistryInfo_OSimpleLogRing(); + createRegistryInfo_OOfficeRestartManager(); + } + } + } + +//........................................................................ +} } // namespace comphelper::module +//........................................................................ + +IMPLEMENT_COMPONENT_LIBRARY_API( ::comphelper::module::ComphelperModule, ::comphelper::module::initializeModule ) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/componentbase.cxx b/comphelper/source/misc/componentbase.cxx new file mode 100644 index 000000000000..0ec5cc0ca93e --- /dev/null +++ b/comphelper/source/misc/componentbase.cxx @@ -0,0 +1,77 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/componentbase.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/NotInitializedException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::lang::NotInitializedException; + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + /** === end UNO using === **/ + + //==================================================================== + //= ComponentBase + //==================================================================== + //-------------------------------------------------------------------- + void ComponentBase::impl_checkDisposed_throw() const + { + if ( m_rBHelper.bDisposed ) + throw DisposedException( ::rtl::OUString(), getComponent() ); + } + + //-------------------------------------------------------------------- + void ComponentBase::impl_checkInitialized_throw() const + { + if ( !m_bInitialized ) + throw NotInitializedException( ::rtl::OUString(), getComponent() ); + } + + //-------------------------------------------------------------------- + Reference< XInterface > ComponentBase::getComponent() const + { + return NULL; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/componentcontext.cxx b/comphelper/source/misc/componentcontext.cxx new file mode 100644 index 000000000000..3334ee1aafc1 --- /dev/null +++ b/comphelper/source/misc/componentcontext.cxx @@ -0,0 +1,153 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/componentcontext.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +/** === end UNO includes === **/ + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::lang::NullPointerException; + using ::com::sun::star::lang::ServiceNotRegisteredException; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Sequence; + /** === end UNO using === **/ + + //==================================================================== + //= ComponentContext + //==================================================================== + //-------------------------------------------------------------------- + ComponentContext::ComponentContext( const Reference< XComponentContext >& _rxContext ) + :m_xContext( _rxContext ) + { + if ( m_xContext.is() ) + m_xORB = m_xContext->getServiceManager(); + if ( !m_xORB.is() ) + throw NullPointerException(); + } + + //------------------------------------------------------------------------ + ComponentContext::ComponentContext( const Reference< XMultiServiceFactory >& _rxLegacyFactory ) + { + if ( !_rxLegacyFactory.is() ) + throw NullPointerException(); + + try + { + Reference< XPropertySet > xFactoryProperties( _rxLegacyFactory, UNO_QUERY_THROW ); + m_xContext = Reference< XComponentContext >( + xFactoryProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), + UNO_QUERY ); + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw RuntimeException(); + } + + if ( m_xContext.is() ) + m_xORB = m_xContext->getServiceManager(); + if ( !m_xORB.is() ) + throw NullPointerException(); + } + + //------------------------------------------------------------------------ + Any ComponentContext::getContextValueByName( const ::rtl::OUString& _rName ) const + { + Any aReturn; + try + { + aReturn = m_xContext->getValueByName( _rName ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ComponentContext::getContextValueByName: caught an exception!" ); + } + return aReturn; + } + + //------------------------------------------------------------------------ + Reference< XInterface > ComponentContext::createComponent( const ::rtl::OUString& _rServiceName ) const + { + Reference< XInterface > xComponent( + m_xORB->createInstanceWithContext( _rServiceName, m_xContext ) + ); + if ( !xComponent.is() ) + throw ServiceNotRegisteredException( _rServiceName, NULL ); + return xComponent; + } + + //------------------------------------------------------------------------ + Reference< XInterface > ComponentContext::createComponentWithArguments( const ::rtl::OUString& _rServiceName, const Sequence< Any >& _rArguments ) const + { + Reference< XInterface > xComponent( + m_xORB->createInstanceWithArgumentsAndContext( _rServiceName, _rArguments, m_xContext ) + ); + if ( !xComponent.is() ) + throw ServiceNotRegisteredException( _rServiceName, NULL ); + return xComponent; + } + + //------------------------------------------------------------------------ + Reference< XInterface > ComponentContext::getSingleton( const ::rtl::OUString& _rInstanceName ) const + { + ::rtl::OUString sKey( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/" ) ) ); + sKey += _rInstanceName; + return Reference< XInterface >( getContextValueByName( sKey ), UNO_QUERY ); + } + + //------------------------------------------------------------------------ + Reference< XMultiServiceFactory > ComponentContext::getLegacyServiceFactory() const + { + return Reference< XMultiServiceFactory >( m_xORB, UNO_QUERY_THROW ); + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/componentmodule.cxx b/comphelper/source/misc/componentmodule.cxx new file mode 100644 index 000000000000..9caf52966980 --- /dev/null +++ b/comphelper/source/misc/componentmodule.cxx @@ -0,0 +1,240 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/componentmodule.hxx> + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ +#include <comphelper/sequence.hxx> +#include <osl/diagnose.h> + +#include <vector> + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + using namespace ::cppu; + /** === being UNO using === **/ + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::registry::XRegistryKey; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::XInterface; + /** === end UNO using === **/ + + typedef ::std::vector< ComponentDescription > ComponentDescriptions; + + //========================================================================= + //= OModuleImpl + //========================================================================= + /** implementation for <type>OModule</type>. not threadsafe, has to be guarded by it's owner + */ + class OModuleImpl + { + public: + ComponentDescriptions m_aRegisteredComponents; + + OModuleImpl(); + ~OModuleImpl(); + }; + + //------------------------------------------------------------------------- + OModuleImpl::OModuleImpl() + { + } + + //------------------------------------------------------------------------- + OModuleImpl::~OModuleImpl() + { + } + + //========================================================================= + //= OModule + //========================================================================= + //------------------------------------------------------------------------- + OModule::OModule() + :m_nClients( 0 ) + ,m_pImpl( new OModuleImpl ) + { + } + + OModule::~OModule() {} + + //------------------------------------------------------------------------- + void OModule::registerClient( OModule::ClientAccess ) + { + ::osl::MutexGuard aGuard(m_aMutex); + if ( 1 == osl_incrementInterlockedCount( &m_nClients ) ) + onFirstClient(); + } + + //------------------------------------------------------------------------- + void OModule::revokeClient( OModule::ClientAccess ) + { + ::osl::MutexGuard aGuard(m_aMutex); + if ( 0 == osl_decrementInterlockedCount( &m_nClients ) ) + onLastClient(); + } + + //-------------------------------------------------------------------------- + void OModule::onFirstClient() + { + } + + //-------------------------------------------------------------------------- + void OModule::onLastClient() + { + } + + //-------------------------------------------------------------------------- + void OModule::registerImplementation( const ComponentDescription& _rComp ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pImpl ) + throw RuntimeException(); + + m_pImpl->m_aRegisteredComponents.push_back( _rComp ); + } + + //-------------------------------------------------------------------------- + void OModule::registerImplementation( const ::rtl::OUString& _rImplementationName, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rServiceNames, + ::cppu::ComponentFactoryFunc _pCreateFunction, FactoryInstantiation _pFactoryFunction ) + { + ComponentDescription aComponent( _rImplementationName, _rServiceNames, ::rtl::OUString(), _pCreateFunction, _pFactoryFunction ); + registerImplementation( aComponent ); + } + + //-------------------------------------------------------------------------- + sal_Bool OModule::writeComponentInfos( void* pServiceManager, void* pRegistryKey ) + { + Reference< XMultiServiceFactory > xFactory( static_cast< XMultiServiceFactory* >( pServiceManager ) ); + Reference< XRegistryKey > xRegistryKey( static_cast< XRegistryKey* >( pRegistryKey ) ); + return writeComponentInfos( xFactory, xRegistryKey ); + } + + //-------------------------------------------------------------------------- + sal_Bool OModule::writeComponentInfos( + const Reference< XMultiServiceFactory >& /*_rxServiceManager*/, + const Reference< XRegistryKey >& _rxRootKey ) + { + OSL_ENSURE( _rxRootKey.is(), "OModule::writeComponentInfos: invalid argument!" ); + + ::rtl::OUString sRootKey( "/", 1, RTL_TEXTENCODING_ASCII_US ); + + for ( ComponentDescriptions::const_iterator component = m_pImpl->m_aRegisteredComponents.begin(); + component != m_pImpl->m_aRegisteredComponents.end(); + ++component + ) + { + ::rtl::OUString sMainKeyName( sRootKey ); + sMainKeyName += component->sImplementationName; + sMainKeyName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")); + + try + { + Reference< XRegistryKey > xNewKey( _rxRootKey->createKey( sMainKeyName ) ); + + const ::rtl::OUString* pService = component->aSupportedServices.getConstArray(); + const ::rtl::OUString* pServiceEnd = component->aSupportedServices.getConstArray() + component->aSupportedServices.getLength(); + for ( ; pService != pServiceEnd; ++pService ) + xNewKey->createKey( *pService ); + + if ( component->sSingletonName.getLength() ) + { + OSL_ENSURE( component->aSupportedServices.getLength() == 1, "OModule::writeComponentInfos: singletons should support exactly one service, shouldn't they?" ); + + ::rtl::OUString sSingletonKeyName( sRootKey ); + sSingletonKeyName += component->sImplementationName; + sSingletonKeyName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SINGLETONS/")); + sSingletonKeyName += component->sSingletonName; + + xNewKey = _rxRootKey->createKey( sSingletonKeyName ); + xNewKey->setStringValue( component->aSupportedServices[ 0 ] ); + } + } + catch( Exception& ) + { + OSL_ASSERT( "OModule::writeComponentInfos: something went wrong while creating the keys!" ); + return sal_False; + } + } + + return sal_True; + } + + //-------------------------------------------------------------------------- + void* OModule::getComponentFactory( const sal_Char* _pImplementationName, void* _pServiceManager, void* /*_pRegistryKey*/ ) + { + Reference< XInterface > xFactory( getComponentFactory( + ::rtl::OUString::createFromAscii( _pImplementationName ), + Reference< XMultiServiceFactory >( static_cast< XMultiServiceFactory* >( _pServiceManager ) ) + ) ); + return xFactory.get(); + } + + //-------------------------------------------------------------------------- + Reference< XInterface > OModule::getComponentFactory( const ::rtl::OUString& _rImplementationName, + const Reference< XMultiServiceFactory >& /* _rxServiceManager */ ) + { + Reference< XInterface > xReturn; + + for ( ComponentDescriptions::const_iterator component = m_pImpl->m_aRegisteredComponents.begin(); + component != m_pImpl->m_aRegisteredComponents.end(); + ++component + ) + { + if ( component->sImplementationName == _rImplementationName ) + { + xReturn = component->pFactoryCreationFunc( + component->pComponentCreationFunc, + component->sImplementationName, + component->aSupportedServices, + NULL + ); + if ( xReturn.is() ) + { + xReturn->acquire(); + return xReturn.get(); + } + } + } + + return NULL; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/configurationhelper.cxx b/comphelper/source/misc/configurationhelper.cxx new file mode 100644 index 000000000000..7ce1bba11dc9 --- /dev/null +++ b/comphelper/source/misc/configurationhelper.cxx @@ -0,0 +1,210 @@ +/* -*- 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 + * <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_comphelper.hxx" + +//_______________________________________________ +// includes +#include <comphelper/configurationhelper.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +//_______________________________________________ +// namespace + +namespace comphelper{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +//----------------------------------------------- +css::uno::Reference< css::uno::XInterface > ConfigurationHelper::openConfig(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR , + const ::rtl::OUString& sPackage, + sal_Int32 eMode ) +{ + css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider( + xSMGR->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider"))), css::uno::UNO_QUERY_THROW); + + ::comphelper::SequenceAsVector< css::uno::Any > lParams; + css::beans::PropertyValue aParam ; + + // set root path + aParam.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath")); + aParam.Value <<= sPackage; + lParams.push_back(css::uno::makeAny(aParam)); + + // enable all locales mode + if ((eMode & ConfigurationHelper::E_ALL_LOCALES)==ConfigurationHelper::E_ALL_LOCALES) + { + aParam.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("locale")); + aParam.Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")); + lParams.push_back(css::uno::makeAny(aParam)); + } + + // enable lazy writing + sal_Bool bLazy = ((eMode & ConfigurationHelper::E_LAZY_WRITE)==ConfigurationHelper::E_LAZY_WRITE); + aParam.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("lazywrite")); + aParam.Value = css::uno::makeAny(bLazy); + lParams.push_back(css::uno::makeAny(aParam)); + + // open it + css::uno::Reference< css::uno::XInterface > xCFG; + + sal_Bool bReadOnly = ((eMode & ConfigurationHelper::E_READONLY)==ConfigurationHelper::E_READONLY); + if (bReadOnly) + xCFG = xConfigProvider->createInstanceWithArguments( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), + lParams.getAsConstList()); + else + xCFG = xConfigProvider->createInstanceWithArguments( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")), + lParams.getAsConstList()); + + return xCFG; +} + +//----------------------------------------------- +css::uno::Any ConfigurationHelper::readRelativeKey(const css::uno::Reference< css::uno::XInterface > xCFG , + const ::rtl::OUString& sRelPath, + const ::rtl::OUString& sKey ) +{ + css::uno::Reference< css::container::XHierarchicalNameAccess > xAccess(xCFG, css::uno::UNO_QUERY_THROW); + + css::uno::Reference< css::beans::XPropertySet > xProps; + xAccess->getByHierarchicalName(sRelPath) >>= xProps; + if (!xProps.is()) + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("The requested path \""); + sMsg.append (sRelPath ); + sMsg.appendAscii("\" does not exists." ); + + throw css::container::NoSuchElementException( + sMsg.makeStringAndClear(), + css::uno::Reference< css::uno::XInterface >()); + } + return xProps->getPropertyValue(sKey); +} + +//----------------------------------------------- +void ConfigurationHelper::writeRelativeKey(const css::uno::Reference< css::uno::XInterface > xCFG , + const ::rtl::OUString& sRelPath, + const ::rtl::OUString& sKey , + const css::uno::Any& aValue ) +{ + css::uno::Reference< css::container::XHierarchicalNameAccess > xAccess(xCFG, css::uno::UNO_QUERY_THROW); + + css::uno::Reference< css::beans::XPropertySet > xProps; + xAccess->getByHierarchicalName(sRelPath) >>= xProps; + if (!xProps.is()) + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("The requested path \""); + sMsg.append (sRelPath ); + sMsg.appendAscii("\" does not exists." ); + + throw css::container::NoSuchElementException( + sMsg.makeStringAndClear(), + css::uno::Reference< css::uno::XInterface >()); + } + xProps->setPropertyValue(sKey, aValue); +} + +//----------------------------------------------- +css::uno::Reference< css::uno::XInterface > ConfigurationHelper::makeSureSetNodeExists(const css::uno::Reference< css::uno::XInterface > xCFG , + const ::rtl::OUString& sRelPathToSet, + const ::rtl::OUString& sSetNode ) +{ + css::uno::Reference< css::container::XHierarchicalNameAccess > xAccess(xCFG, css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::container::XNameAccess > xSet; + xAccess->getByHierarchicalName(sRelPathToSet) >>= xSet; + if (!xSet.is()) + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("The requested path \""); + sMsg.append (sRelPathToSet ); + sMsg.appendAscii("\" does not exists." ); + + throw css::container::NoSuchElementException( + sMsg.makeStringAndClear(), + css::uno::Reference< css::uno::XInterface >()); + } + + css::uno::Reference< css::uno::XInterface > xNode; + if (xSet->hasByName(sSetNode)) + xSet->getByName(sSetNode) >>= xNode; + else + { + css::uno::Reference< css::lang::XSingleServiceFactory > xNodeFactory(xSet, css::uno::UNO_QUERY_THROW); + xNode = xNodeFactory->createInstance(); + css::uno::Reference< css::container::XNameContainer > xSetReplace(xSet, css::uno::UNO_QUERY_THROW); + xSetReplace->insertByName(sSetNode, css::uno::makeAny(xNode)); + } + + return xNode; +} + +//----------------------------------------------- +css::uno::Any ConfigurationHelper::readDirectKey(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR , + const ::rtl::OUString& sPackage, + const ::rtl::OUString& sRelPath, + const ::rtl::OUString& sKey , + sal_Int32 eMode ) +{ + css::uno::Reference< css::uno::XInterface > xCFG = ConfigurationHelper::openConfig(xSMGR, sPackage, eMode); + return ConfigurationHelper::readRelativeKey(xCFG, sRelPath, sKey); +} + +//----------------------------------------------- +void ConfigurationHelper::writeDirectKey(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR , + const ::rtl::OUString& sPackage, + const ::rtl::OUString& sRelPath, + const ::rtl::OUString& sKey , + const css::uno::Any& aValue , + sal_Int32 eMode ) +{ + css::uno::Reference< css::uno::XInterface > xCFG = ConfigurationHelper::openConfig(xSMGR, sPackage, eMode); + ConfigurationHelper::writeRelativeKey(xCFG, sRelPath, sKey, aValue); + ConfigurationHelper::flush(xCFG); +} + +//----------------------------------------------- +void ConfigurationHelper::flush(const css::uno::Reference< css::uno::XInterface >& xCFG) +{ + css::uno::Reference< css::util::XChangesBatch > xBatch(xCFG, css::uno::UNO_QUERY_THROW); + xBatch->commitChanges(); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx new file mode 100644 index 000000000000..9a0c8a0e498a --- /dev/null +++ b/comphelper/source/misc/docpasswordhelper.cxx @@ -0,0 +1,382 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/docpasswordhelper.hxx" +#include <com/sun/star/task/XInteractionHandler.hpp> +#include "comphelper/mediadescriptor.hxx" + +#include <osl/time.h> +#include <rtl/digest.h> +#include <rtl/random.h> + +using ::rtl::OUString; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::task::PasswordRequestMode; +using ::com::sun::star::task::PasswordRequestMode_PASSWORD_ENTER; +using ::com::sun::star::task::PasswordRequestMode_PASSWORD_REENTER; +using ::com::sun::star::task::XInteractionHandler; +using ::com::sun::star::task::XInteractionRequest; + +using namespace ::com::sun::star; + +namespace comphelper { + +// ============================================================================ + +static uno::Sequence< sal_Int8 > GeneratePBKDF2Hash( const ::rtl::OUString& aPassword, const uno::Sequence< sal_Int8 >& aSalt, sal_Int32 nCount, sal_Int32 nHashLength ) +{ + uno::Sequence< sal_Int8 > aResult; + + if ( aPassword.getLength() && aSalt.getLength() && nCount && nHashLength ) + { + ::rtl::OString aBytePass = ::rtl::OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ); + aResult.realloc( 16 ); + rtl_digest_PBKDF2( reinterpret_cast < sal_uInt8 * > ( aResult.getArray() ), + aResult.getLength(), + reinterpret_cast < const sal_uInt8 * > ( aBytePass.getStr() ), + aBytePass.getLength(), + reinterpret_cast < const sal_uInt8 * > ( aSalt.getConstArray() ), + aSalt.getLength(), + nCount ); + } + + return aResult; +} + +// ============================================================================ + +IDocPasswordVerifier::~IDocPasswordVerifier() +{ +} + +// ============================================================================ +uno::Sequence< beans::PropertyValue > DocPasswordHelper::GenerateNewModifyPasswordInfo( const ::rtl::OUString& aPassword ) +{ + uno::Sequence< beans::PropertyValue > aResult; + + uno::Sequence< sal_Int8 > aSalt( 16 ); + sal_Int32 nCount = 1024; + + TimeValue aTime; + osl_getSystemTime( &aTime ); + rtlRandomPool aRandomPool = rtl_random_createPool (); + rtl_random_addBytes ( aRandomPool, &aTime, 8 ); + + rtl_random_getBytes ( aRandomPool, aSalt.getArray(), 16 ); + + uno::Sequence< sal_Int8 > aNewHash = GeneratePBKDF2Hash( aPassword, aSalt, nCount, 16 ); + if ( aNewHash.getLength() ) + { + aResult.realloc( 4 ); + aResult[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "algorithm-name" ) ); + aResult[0].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PBKDF2" ) ); + aResult[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "salt" ) ); + aResult[1].Value <<= aSalt; + aResult[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "iteration-count" ) ); + aResult[2].Value <<= nCount; + aResult[3].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hash" ) ); + aResult[3].Value <<= aNewHash; + } + + // Clean up random pool memory + rtl_random_destroyPool ( aRandomPool ); + + return aResult; +} + +// ============================================================================ +sal_Bool DocPasswordHelper::IsModifyPasswordCorrect( const ::rtl::OUString& aPassword, const uno::Sequence< beans::PropertyValue >& aInfo ) +{ + sal_Bool bResult = sal_False; + if ( aPassword.getLength() && aInfo.getLength() ) + { + ::rtl::OUString sAlgorithm; + uno::Sequence< sal_Int8 > aSalt; + uno::Sequence< sal_Int8 > aHash; + sal_Int32 nCount = 0; + + for ( sal_Int32 nInd = 0; nInd < aInfo.getLength(); nInd++ ) + { + if ( aInfo[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "algorithm-name" ) ) ) ) + aInfo[nInd].Value >>= sAlgorithm; + else if ( aInfo[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "salt" ) ) ) ) + aInfo[nInd].Value >>= aSalt; + else if ( aInfo[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "iteration-count" ) ) ) ) + aInfo[nInd].Value >>= nCount; + else if ( aInfo[nInd].Name.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "hash" ) ) ) ) + aInfo[nInd].Value >>= aHash; + } + + if ( sAlgorithm.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PBKDF2" ) ) ) + && aSalt.getLength() && nCount > 0 && aHash.getLength() ) + { + uno::Sequence< sal_Int8 > aNewHash = GeneratePBKDF2Hash( aPassword, aSalt, nCount, aHash.getLength() ); + for ( sal_Int32 nInd = 0; nInd < aNewHash.getLength() && nInd < aHash.getLength() && aNewHash[nInd] == aHash[nInd]; nInd ++ ) + { + if ( nInd == aNewHash.getLength() - 1 && nInd == aHash.getLength() - 1 ) + bResult = sal_True; + } + } + } + + return bResult; +} + +// ============================================================================ +sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( + const ::rtl::OUString& aUString ) +{ + static sal_uInt16 pInitialCode[] = { + 0xE1F0, // 1 + 0x1D0F, // 2 + 0xCC9C, // 3 + 0x84C0, // 4 + 0x110C, // 5 + 0x0E10, // 6 + 0xF1CE, // 7 + 0x313E, // 8 + 0x1872, // 9 + 0xE139, // 10 + 0xD40F, // 11 + 0x84F9, // 12 + 0x280C, // 13 + 0xA96A, // 14 + 0x4EC3 // 15 + }; + + static sal_uInt16 pEncryptionMatrix[15][7] = { + { 0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09}, // last-14 + { 0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF}, // last-13 + { 0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0}, // last-12 + { 0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40}, // last-11 + { 0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5}, // last-10 + { 0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A}, // last-9 + { 0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9}, // last-8 + { 0x47D3, 0x8FA6, 0x8FA6, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0}, // last-7 + { 0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC}, // last-6 + { 0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10}, // last-5 + { 0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168}, // last-4 + { 0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C}, // last-3 + { 0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD}, // last-2 + { 0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC}, // last-1 + { 0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4} // last + }; + + sal_uInt32 nResult = 0; + sal_uInt32 nLen = aUString.getLength(); + + if ( nLen ) + { + if ( nLen > 15 ) + nLen = 15; + + sal_uInt16 nHighResult = pInitialCode[nLen - 1]; + sal_uInt16 nLowResult = 0; + + const sal_Unicode* pStr = aUString.getStr(); + for ( sal_uInt32 nInd = 0; nInd < nLen; nInd++ ) + { + // NO Encoding during conversion! + // The specification says that the low byte should be used in case it is not NULL + char nHighChar = (char)( pStr[nInd] >> 8 ); + char nLowChar = (char)( pStr[nInd] & 0xFF ); + char nChar = nLowChar ? nLowChar : nHighChar; + + for ( int nMatrixInd = 0; nMatrixInd < 7; ++nMatrixInd ) + { + if ( ( nChar & ( 1 << nMatrixInd ) ) != 0 ) + nHighResult = nHighResult ^ pEncryptionMatrix[15 - nLen + nInd][nMatrixInd]; + } + + nLowResult = ( ( ( nLowResult >> 14 ) & 0x0001 ) | ( ( nLowResult << 1 ) & 0x7FFF ) ) ^ nChar; + } + + nLowResult = (sal_uInt16)( ( ( ( nLowResult >> 14 ) & 0x001 ) | ( ( nLowResult << 1 ) & 0x7FF ) ) ^ nLen ^ 0xCE4B ); + + nResult = ( nHighResult << 16 ) | nLowResult; + } + + return nResult; +} + +// ============================================================================ +Sequence< sal_Int8 > DocPasswordHelper::GetWordHashAsSequence( + const ::rtl::OUString& aUString ) +{ + sal_uInt32 nHash = GetWordHashAsUINT32( aUString ); + Sequence< sal_Int8 > aResult( 4 ); + aResult[0] = ( nHash >> 24 ); + aResult[1] = ( ( nHash >> 16 ) & 0xFF ); + aResult[2] = ( ( nHash >> 8 ) & 0xFF ); + aResult[3] = ( nHash & 0xFF ); + + return aResult; +} + +// ============================================================================ +sal_uInt16 DocPasswordHelper::GetXLHashAsUINT16( + const ::rtl::OUString& aUString, + rtl_TextEncoding nEnc ) +{ + sal_uInt16 nResult = 0; + + ::rtl::OString aString = ::rtl::OUStringToOString( aUString, nEnc ); + + if ( aString.getLength() && aString.getLength() <= SAL_MAX_UINT16 ) + { + for ( sal_Int32 nInd = aString.getLength() - 1; nInd >= 0; nInd-- ) + { + nResult = ( ( nResult >> 14 ) & 0x01 ) | ( ( nResult << 1 ) & 0x7FFF ); + nResult ^= aString.getStr()[nInd]; + } + + nResult = ( ( nResult >> 14 ) & 0x01 ) | ( ( nResult << 1 ) & 0x7FFF ); + nResult ^= ( 0x8000 | ( 'N' << 8 ) | 'K' ); + nResult ^= aString.getLength(); + } + + return nResult; +} + +// ============================================================================ +Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence( + const ::rtl::OUString& aUString, + rtl_TextEncoding nEnc ) +{ + sal_uInt16 nHash = GetXLHashAsUINT16( aUString, nEnc ); + Sequence< sal_Int8 > aResult( 2 ); + aResult[0] = ( nHash >> 8 ); + aResult[1] = ( nHash & 0xFF ); + + return aResult; +} + +// ============================================================================ + +/*static*/ OUString DocPasswordHelper::requestAndVerifyDocPassword( + IDocPasswordVerifier& rVerifier, + const OUString& rMediaPassword, + const Reference< XInteractionHandler >& rxInteractHandler, + const OUString& rDocumentName, + DocPasswordRequestType eRequestType, + const ::std::vector< OUString >* pDefaultPasswords, + bool* pbIsDefaultPassword ) +{ + OUString aPassword; + DocPasswordVerifierResult eResult = DocPasswordVerifierResult_WRONG_PASSWORD; + + // first, try provided default passwords + if( pbIsDefaultPassword ) + *pbIsDefaultPassword = false; + if( pDefaultPasswords ) + { + for( ::std::vector< OUString >::const_iterator aIt = pDefaultPasswords->begin(), aEnd = pDefaultPasswords->end(); (eResult == DocPasswordVerifierResult_WRONG_PASSWORD) && (aIt != aEnd); ++aIt ) + { + aPassword = *aIt; + OSL_ENSURE( aPassword.getLength() > 0, "DocPasswordHelper::requestAndVerifyDocPassword - unexpected empty default password" ); + if( aPassword.getLength() > 0 ) + { + eResult = rVerifier.verifyPassword( aPassword ); + if( pbIsDefaultPassword ) + *pbIsDefaultPassword = eResult == DocPasswordVerifierResult_OK; + } + } + } + + // try media password (skip, if result is OK or ABORT) + if( eResult == DocPasswordVerifierResult_WRONG_PASSWORD ) + { + aPassword = rMediaPassword; + if( aPassword.getLength() > 0 ) + eResult = rVerifier.verifyPassword( aPassword ); + } + + // request a password (skip, if result is OK or ABORT) + if( (eResult == DocPasswordVerifierResult_WRONG_PASSWORD) && rxInteractHandler.is() ) try + { + PasswordRequestMode eRequestMode = PasswordRequestMode_PASSWORD_ENTER; + while( eResult == DocPasswordVerifierResult_WRONG_PASSWORD ) + { + DocPasswordRequest* pRequest = new DocPasswordRequest( eRequestType, eRequestMode, rDocumentName ); + Reference< XInteractionRequest > xRequest( pRequest ); + rxInteractHandler->handle( xRequest ); + if( pRequest->isPassword() ) + { + aPassword = pRequest->getPassword(); + if( aPassword.getLength() > 0 ) + eResult = rVerifier.verifyPassword( aPassword ); + } + else + { + eResult = DocPasswordVerifierResult_ABORT; + } + eRequestMode = PasswordRequestMode_PASSWORD_REENTER; + } + } + catch( Exception& ) + { + } + + return (eResult == DocPasswordVerifierResult_OK) ? aPassword : OUString(); +} + +/*static*/ OUString DocPasswordHelper::requestAndVerifyDocPassword( + IDocPasswordVerifier& rVerifier, + MediaDescriptor& rMediaDesc, + DocPasswordRequestType eRequestType, + const ::std::vector< OUString >* pDefaultPasswords ) +{ + OUString aMediaPassword = rMediaDesc.getUnpackedValueOrDefault( + MediaDescriptor::PROP_PASSWORD(), OUString() ); + Reference< XInteractionHandler > xInteractHandler = rMediaDesc.getUnpackedValueOrDefault( + MediaDescriptor::PROP_INTERACTIONHANDLER(), Reference< XInteractionHandler >() ); + OUString aDocumentName = rMediaDesc.getUnpackedValueOrDefault( + MediaDescriptor::PROP_URL(), OUString() ); + + bool bIsDefaultPassword = false; + OUString aPassword = requestAndVerifyDocPassword( + rVerifier, aMediaPassword, xInteractHandler, aDocumentName, eRequestType, pDefaultPasswords, &bIsDefaultPassword ); + + // insert valid password into media descriptor (but not a default password) + if( (aPassword.getLength() > 0) && !bIsDefaultPassword ) + rMediaDesc[ MediaDescriptor::PROP_PASSWORD() ] <<= aPassword; + + return aPassword; +} + +// ============================================================================ + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/docpasswordrequest.cxx b/comphelper/source/misc/docpasswordrequest.cxx new file mode 100644 index 000000000000..49e941601123 --- /dev/null +++ b/comphelper/source/misc/docpasswordrequest.cxx @@ -0,0 +1,196 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/docpasswordrequest.hxx" +#include <com/sun/star/task/DocumentMSPasswordRequest2.hpp> +#include <com/sun/star/task/DocumentPasswordRequest2.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionPassword2.hpp> + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Type; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::task::InteractionClassification_QUERY; +using ::com::sun::star::task::DocumentMSPasswordRequest2; +using ::com::sun::star::task::DocumentPasswordRequest2; +using ::com::sun::star::task::PasswordRequestMode; +using ::com::sun::star::task::XInteractionAbort; +using ::com::sun::star::task::XInteractionContinuation; +using ::com::sun::star::task::XInteractionPassword2; +using ::com::sun::star::task::XInteractionRequest; + +namespace comphelper { + +// ============================================================================ + +class AbortContinuation : public ::cppu::WeakImplHelper1< XInteractionAbort > +{ +public: + inline explicit AbortContinuation() : mbSelected( false ) {} + + inline sal_Bool isSelected() const { return mbSelected; } + inline void reset() { mbSelected = false; } + + virtual void SAL_CALL select() throw( RuntimeException ) { mbSelected = true; } + +private: + sal_Bool mbSelected; +}; + +// ============================================================================ + +class PasswordContinuation : public ::cppu::WeakImplHelper1< XInteractionPassword2 > +{ +public: + inline explicit PasswordContinuation() : mbReadOnly( sal_False ), mbSelected( sal_False ) {} + + inline sal_Bool isSelected() const { return mbSelected; } + inline void reset() { mbSelected = sal_False; } + + virtual void SAL_CALL select() throw( RuntimeException ) { mbSelected = sal_True; } + + virtual void SAL_CALL setPassword( const OUString& rPass ) throw( RuntimeException ) { maPassword = rPass; } + virtual OUString SAL_CALL getPassword() throw( RuntimeException ) { return maPassword; } + + virtual void SAL_CALL setPasswordToModify( const OUString& rPass ) throw( RuntimeException ) { maModifyPassword = rPass; } + virtual OUString SAL_CALL getPasswordToModify() throw( RuntimeException ) { return maModifyPassword; } + + virtual void SAL_CALL setRecommendReadOnly( sal_Bool bReadOnly ) throw( RuntimeException ) { mbReadOnly = bReadOnly; } + virtual sal_Bool SAL_CALL getRecommendReadOnly() throw( RuntimeException ) { return mbReadOnly; } + +private: + OUString maPassword; + OUString maModifyPassword; + sal_Bool mbReadOnly; + sal_Bool mbSelected; +}; + +// ============================================================================ + +DocPasswordRequest::DocPasswordRequest( DocPasswordRequestType eType, + PasswordRequestMode eMode, const OUString& rDocumentName, sal_Bool bPasswordToModify ) +: mpAbort( NULL ) +, mpPassword( NULL ) +, mbPasswordToModify( bPasswordToModify ) +{ + switch( eType ) + { + case DocPasswordRequestType_STANDARD: + { + DocumentPasswordRequest2 aRequest( OUString(), Reference< XInterface >(), + InteractionClassification_QUERY, eMode, rDocumentName, bPasswordToModify ); + maRequest <<= aRequest; + } + break; + case DocPasswordRequestType_MS: + { + DocumentMSPasswordRequest2 aRequest( OUString(), Reference< XInterface >(), + InteractionClassification_QUERY, eMode, rDocumentName, bPasswordToModify ); + maRequest <<= aRequest; + } + break; + /* no 'default', so compilers will complain about missing + implementation of a new enum value. */ + } + + maContinuations.realloc( 2 ); + maContinuations[ 0 ].set( mpAbort = new AbortContinuation ); + maContinuations[ 1 ].set( mpPassword = new PasswordContinuation ); +} + +DocPasswordRequest::~DocPasswordRequest() +{ +} + +/*uno::*/Any SAL_CALL DocPasswordRequest::queryInterface( const /*uno::*/Type& rType ) throw (RuntimeException) +{ + return ::cppu::queryInterface ( rType, + // OWeakObject interfaces + dynamic_cast< XInterface* > ( (XInteractionRequest *) this ), + static_cast< XWeak* > ( this ), + // my own interfaces + static_cast< XInteractionRequest* > ( this ) ); +} + +void SAL_CALL DocPasswordRequest::acquire( ) throw () +{ + OWeakObject::acquire(); +} + +void SAL_CALL DocPasswordRequest::release( ) throw () +{ + OWeakObject::release(); +} + +sal_Bool DocPasswordRequest::isAbort() const +{ + return mpAbort->isSelected(); +} + +sal_Bool DocPasswordRequest::isPassword() const +{ + return mpPassword->isSelected(); +} + +OUString DocPasswordRequest::getPassword() const +{ + return mpPassword->getPassword(); +} + +OUString DocPasswordRequest::getPasswordToModify() const +{ + return mpPassword->getPasswordToModify(); +} + +sal_Bool DocPasswordRequest::getRecommendReadOnly() const +{ + return mpPassword->getRecommendReadOnly(); +} + +Any SAL_CALL DocPasswordRequest::getRequest() throw( RuntimeException ) +{ + return maRequest; +} + +Sequence< Reference< XInteractionContinuation > > SAL_CALL DocPasswordRequest::getContinuations() throw( RuntimeException ) +{ + return maContinuations; +} + +// ============================================================================ + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/documentinfo.cxx b/comphelper/source/misc/documentinfo.cxx new file mode 100644 index 000000000000..256c50f93f91 --- /dev/null +++ b/comphelper/source/misc/documentinfo.cxx @@ -0,0 +1,200 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/documentinfo.hxx" +#include "comphelper/namedvaluecollection.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/frame/XTitle.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/exc_hlp.hxx> + +#include <osl/diagnose.h> +#include <osl/thread.h> + +#include <boost/current_function.hpp> + +//........................................................................ +namespace comphelper { +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::frame::XTitle; + using ::com::sun::star::frame::XController; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::document::XDocumentPropertiesSupplier; + using ::com::sun::star::document::XDocumentProperties; + using ::com::sun::star::frame::XStorable; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::frame::XTitle; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::frame::XFrame; + /** === end UNO using === **/ + + //==================================================================== + //= helper + //==================================================================== + namespace + { + ::rtl::OUString lcl_getTitle( const Reference< XInterface >& _rxComponent ) + { + Reference< XTitle > xTitle( _rxComponent, UNO_QUERY ); + if ( xTitle.is() ) + return xTitle->getTitle(); + return ::rtl::OUString(); + } + } + + //==================================================================== + //= DocumentInfo + //==================================================================== + //-------------------------------------------------------------------- + ::rtl::OUString DocumentInfo::getDocumentTitle( const Reference< XModel >& _rxDocument ) + { + ::rtl::OUString sTitle; + + if ( !_rxDocument.is() ) + return sTitle; + + ::rtl::OUString sDocURL; + try + { + // 1. ask the model and the controller for their XTitle::getTitle + sTitle = lcl_getTitle( _rxDocument ); + if ( sTitle.getLength() ) + return sTitle; + + Reference< XController > xController( _rxDocument->getCurrentController() ); + sTitle = lcl_getTitle( xController ); + if ( sTitle.getLength() ) + return sTitle; + + // work around a problem with embedded objects, which sometimes return + // private:object as URL + sDocURL = _rxDocument->getURL(); + if ( sDocURL.matchAsciiL( "private:", 8 ) ) + sDocURL = ::rtl::OUString(); + + // 2. if the document is not saved, yet, check the frame title + if ( sDocURL.getLength() == 0 ) + { + Reference< XFrame > xFrame; + if ( xController.is() ) + xFrame.set( xController->getFrame() ); + sTitle = lcl_getTitle( xFrame ); + if ( sTitle.getLength() ) + return sTitle; + } + + // 3. try the UNO DocumentInfo + Reference< XDocumentPropertiesSupplier > xDPS( _rxDocument, UNO_QUERY ); + if ( xDPS.is() ) + { + Reference< XDocumentProperties > xDocProps ( + xDPS->getDocumentProperties(), UNO_QUERY_THROW ); + OSL_ENSURE(xDocProps.is(), "no DocumentProperties"); + sTitle = xDocProps->getTitle(); + if ( sTitle.getLength() ) + return sTitle; + } + + // 4. try model arguments + NamedValueCollection aModelArgs( _rxDocument->getArgs() ); + sTitle = aModelArgs.getOrDefault( "Title", sTitle ); + if ( sTitle.getLength() ) + return sTitle; + + // 5. try the last segment of the document URL + // this formerly was an INetURLObject::getName( LAST_SEGMENT, true, DECODE_WITH_CHARSET ), + // but since we moved this code to comphelper, we do not have access to an INetURLObject anymore + // This heuristics here should be sufficient - finally, we will get an UNO title API in a not + // too distant future (hopefully), then this complete class is superfluous) + if ( sDocURL.getLength() == 0 ) + { + Reference< XStorable > xDocStorable( _rxDocument, UNO_QUERY_THROW ); + sDocURL = xDocStorable->getLocation(); + } + sal_Int32 nLastSepPos = sDocURL.lastIndexOf( '/' ); + if ( ( nLastSepPos != -1 ) && ( nLastSepPos == sDocURL.getLength() - 1 ) ) + { + sDocURL = sDocURL.copy( 0, nLastSepPos ); + nLastSepPos = sDocURL.lastIndexOf( '/' ); + } + sTitle = sDocURL.copy( nLastSepPos + 1 ); + + if ( sTitle.getLength() != 0 ) + return sTitle; + + // 5. + // <-- #i88104# (05-16-08) TKR: use the new XTitle Interface to get the Title --> + + Reference< XTitle > xTitle( _rxDocument, UNO_QUERY ); + if ( xTitle.is() ) + { + if ( xTitle->getTitle().getLength() != 0 ) + return xTitle->getTitle(); + } + } + catch ( const Exception& ) + { + ::com::sun::star::uno::Any caught( ::cppu::getCaughtException() ); + ::rtl::OString sMessage( "caught an exception!" ); + sMessage += "\ntype : "; + sMessage += ::rtl::OString( caught.getValueTypeName().getStr(), caught.getValueTypeName().getLength(), osl_getThreadTextEncoding() ); + sMessage += "\nmessage: "; + ::com::sun::star::uno::Exception exception; + caught >>= exception; + sMessage += ::rtl::OString( exception.Message.getStr(), exception.Message.getLength(), osl_getThreadTextEncoding() ); + sMessage += "\nin function:\n"; + sMessage += BOOST_CURRENT_FUNCTION; + sMessage += "\n"; + OSL_ENSURE( false, sMessage ); + } + + return sTitle; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/documentiologring.cxx b/comphelper/source/misc/documentiologring.cxx new file mode 100644 index 000000000000..c4b77338e798 --- /dev/null +++ b/comphelper/source/misc/documentiologring.cxx @@ -0,0 +1,182 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include <com/sun/star/frame/DoubleInitializationException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <comphelper_module.hxx> + +#include "documentiologring.hxx" + +using namespace ::com::sun::star; + +namespace comphelper +{ + +// ---------------------------------------------------------- +OSimpleLogRing::OSimpleLogRing( const uno::Reference< uno::XComponentContext >& /*xContext*/ ) +: m_aMessages( SIMPLELOGRING_SIZE ) +, m_bInitialized( sal_False ) +, m_bFull( sal_False ) +, m_nPos( 0 ) +{ +} + +// ---------------------------------------------------------- +OSimpleLogRing::~OSimpleLogRing() +{ +} + +// ---------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OSimpleLogRing::getSupportedServiceNames_static() +{ + uno::Sequence< rtl::OUString > aResult( 1 ); + aResult[0] = getServiceName_static(); + return aResult; +} + +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OSimpleLogRing::getImplementationName_static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.logging.SimpleLogRing" ) ); +} + +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OSimpleLogRing::getSingletonName_static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.DocumentIOLogRing" ) ); +} + +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OSimpleLogRing::getServiceName_static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.SimpleLogRing" ) ); +} + +// ---------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OSimpleLogRing::Create( const uno::Reference< uno::XComponentContext >& rxContext ) +{ + return static_cast< cppu::OWeakObject* >( new OSimpleLogRing( rxContext ) ); +} + +// XSimpleLogRing +// ---------------------------------------------------------- +void SAL_CALL OSimpleLogRing::logString( const ::rtl::OUString& aMessage ) throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_aMessages[m_nPos] = aMessage; + if ( ++m_nPos >= m_aMessages.getLength() ) + { + m_nPos = 0; + m_bFull = sal_True; + } + + // if used once then default initialized + m_bInitialized = sal_True; +} + +// ---------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OSimpleLogRing::getCollectedLog() throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + sal_Int32 nResLen = m_bFull ? m_aMessages.getLength() : m_nPos; + sal_Int32 nStart = m_bFull ? m_nPos : 0; + uno::Sequence< ::rtl::OUString > aResult( nResLen ); + + for ( sal_Int32 nInd = 0; nInd < nResLen; nInd++ ) + aResult[nInd] = m_aMessages[ ( nStart + nInd ) % m_aMessages.getLength() ]; + + // if used once then default initialized + m_bInitialized = sal_True; + + return aResult; +} + +// XInitialization +// ---------------------------------------------------------- +void SAL_CALL OSimpleLogRing::initialize( const uno::Sequence< uno::Any >& aArguments ) throw (uno::Exception, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bInitialized ) + throw frame::DoubleInitializationException(); + + if ( !m_refCount ) + throw uno::RuntimeException(); // the object must be refcounted already! + + sal_Int32 nLen = 0; + if ( aArguments.getLength() == 1 && ( aArguments[0] >>= nLen ) && nLen ) + m_aMessages.realloc( nLen ); + else + throw lang::IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonnull size is expected as the first argument!" ) ), + uno::Reference< uno::XInterface >(), + 0 ); + + m_bInitialized = sal_True; +} + +// XServiceInfo +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OSimpleLogRing::getImplementationName() throw (uno::RuntimeException) +{ + return getImplementationName_static(); +} + +// ---------------------------------------------------------- +::sal_Bool SAL_CALL OSimpleLogRing::supportsService( const ::rtl::OUString& aServiceName ) throw (uno::RuntimeException) +{ + const uno::Sequence< rtl::OUString > & aSupportedNames = getSupportedServiceNames_static(); + for ( sal_Int32 nInd = 0; nInd < aSupportedNames.getLength(); nInd++ ) + { + if ( aSupportedNames[ nInd ].equals( aServiceName ) ) + return sal_True; + } + + return sal_False; +} + +// ---------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OSimpleLogRing::getSupportedServiceNames() throw (uno::RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +} // namespace comphelper + +void createRegistryInfo_OSimpleLogRing() +{ + static ::comphelper::module::OAutoRegistration< ::comphelper::OSimpleLogRing > aAutoRegistration; + static ::comphelper::module::OSingletonRegistration< ::comphelper::OSimpleLogRing > aSingletonRegistration; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/documentiologring.hxx b/comphelper/source/misc/documentiologring.hxx new file mode 100644 index 000000000000..a01a37de2eae --- /dev/null +++ b/comphelper/source/misc/documentiologring.hxx @@ -0,0 +1,90 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __DOCUMENTIOLOGRING_HXX_ +#define __DOCUMENTIOLOGRING_HXX_ + +#include <com/sun/star/logging/XSimpleLogRing.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> + +#include <osl/mutex.hxx> +#include <cppuhelper/implbase3.hxx> + +#define SIMPLELOGRING_SIZE 256 + +namespace comphelper +{ + +class OSimpleLogRing : public ::cppu::WeakImplHelper3< ::com::sun::star::logging::XSimpleLogRing, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::lang::XServiceInfo > +{ + ::osl::Mutex m_aMutex; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aMessages; + + sal_Bool m_bInitialized; + sal_Bool m_bFull; + sal_Int32 m_nPos; + +public: + OSimpleLogRing( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext ); + virtual ~OSimpleLogRing(); + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames_static(); + + static ::rtl::OUString SAL_CALL getImplementationName_static(); + + static ::rtl::OUString SAL_CALL getSingletonName_static(); + + static ::rtl::OUString SAL_CALL getServiceName_static(); + + 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 >& rxContext ); + +// XSimpleLogRing + virtual void SAL_CALL logString( const ::rtl::OUString& aMessage ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getCollectedLog() throw (::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); + +// 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); + +}; + +} // namespace comphelper + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/evtlistenerhlp.cxx b/comphelper/source/misc/evtlistenerhlp.cxx new file mode 100644 index 000000000000..2459d9160303 --- /dev/null +++ b/comphelper/source/misc/evtlistenerhlp.cxx @@ -0,0 +1,54 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include "comphelper/evtlistenerhlp.hxx" + +namespace comphelper +{ + OEventListenerHelper::OEventListenerHelper(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener>& + _rxListener) : m_xListener(_rxListener) + { + } + void SAL_CALL OEventListenerHelper::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException) + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener> xRef = m_xListener; + if(xRef.is()) + xRef->disposing(Source); + } +} + + + + + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/evtmethodhelper.cxx b/comphelper/source/misc/evtmethodhelper.cxx new file mode 100644 index 000000000000..4fe780630718 --- /dev/null +++ b/comphelper/source/misc/evtmethodhelper.cxx @@ -0,0 +1,79 @@ +/* -*- 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 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: evtlistenerhlp.cxx,v $ + * $Revision$ + * + * 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_comphelper.hxx" +#include "comphelper/evtmethodhelper.hxx" +#include "cppuhelper/typeprovider.hxx" + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Type; + +namespace comphelper +{ + + Sequence< ::rtl::OUString> getEventMethodsForType(const Type& type) + { + typelib_InterfaceTypeDescription *pType=0; + type.getDescription( (typelib_TypeDescription**)&pType); + + if(!pType) + return Sequence< ::rtl::OUString>(); + + Sequence< ::rtl::OUString> aNames(pType->nMembers); + ::rtl::OUString* pNames = aNames.getArray(); + for(sal_Int32 i=0;i<pType->nMembers;i++,++pNames) + { + // the decription reference + typelib_TypeDescriptionReference* pMemberDescriptionReference = pType->ppMembers[i]; + // the description for the reference + typelib_TypeDescription* pMemberDescription = NULL; + typelib_typedescriptionreference_getDescription(&pMemberDescription, pMemberDescriptionReference); + if (pMemberDescription) + { + typelib_InterfaceMemberTypeDescription* pRealMemberDescription = + reinterpret_cast<typelib_InterfaceMemberTypeDescription*>(pMemberDescription); + *pNames = pRealMemberDescription->pMemberName; + } + } + typelib_typedescription_release( (typelib_TypeDescription *)pType ); + return aNames; + } + +} + + + + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/ihwrapnofilter.cxx b/comphelper/source/misc/ihwrapnofilter.cxx new file mode 100644 index 000000000000..5ee98ca4c1ba --- /dev/null +++ b/comphelper/source/misc/ihwrapnofilter.cxx @@ -0,0 +1,120 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_comphelper.hxx" + +#include "comphelper/ihwrapnofilter.hxx" +#include <com/sun/star/document/NoSuchFilterRequest.hpp> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + + using namespace ::com::sun::star; + + //---------------------------------------------------------------------------------------------------- + OIHWrapNoFilterDialog::OIHWrapNoFilterDialog( uno::Reference< task::XInteractionHandler > xInteraction ) + :m_xInter( xInteraction ) + { + } + + OIHWrapNoFilterDialog::~OIHWrapNoFilterDialog() + { + } + + //---------------------------------------------------------------------------------------------------- + uno::Sequence< ::rtl::OUString > SAL_CALL OIHWrapNoFilterDialog::impl_staticGetSupportedServiceNames() + { + uno::Sequence< ::rtl::OUString > aRet(1); + aRet[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandlerWrapper")); + return aRet; + } + + ::rtl::OUString SAL_CALL OIHWrapNoFilterDialog::impl_staticGetImplementationName() + { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.task.InteractionHandlerWrapper")); + } + + //---------------------------------------------------------------------------------------------------- + // XInteractionHandler + //---------------------------------------------------------------------------------------------------- + void SAL_CALL OIHWrapNoFilterDialog::handle( const uno::Reference< task::XInteractionRequest >& xRequest) + throw( com::sun::star::uno::RuntimeException ) + { + if( !m_xInter.is() ) + return; + + uno::Any aRequest = xRequest->getRequest(); + document::NoSuchFilterRequest aNoSuchFilterRequest; + if ( aRequest >>= aNoSuchFilterRequest ) + return; + else + m_xInter->handle( xRequest ); + } + + //---------------------------------------------------------------------------------------------------- + // XInitialization + //---------------------------------------------------------------------------------------------------- + void SAL_CALL OIHWrapNoFilterDialog::initialize( const uno::Sequence< uno::Any >& ) + throw ( uno::Exception, + uno::RuntimeException, + frame::DoubleInitializationException ) + { + } + + //---------------------------------------------------------------------------------------------------- + // XServiceInfo + //---------------------------------------------------------------------------------------------------- + + ::rtl::OUString SAL_CALL OIHWrapNoFilterDialog::getImplementationName() + throw ( uno::RuntimeException ) + { + return impl_staticGetImplementationName(); + } + + ::sal_Bool SAL_CALL OIHWrapNoFilterDialog::supportsService( const ::rtl::OUString& ServiceName ) + throw ( uno::RuntimeException ) + { + uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); + + for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) + if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) + return sal_True; + + return sal_False; + } + + uno::Sequence< ::rtl::OUString > SAL_CALL OIHWrapNoFilterDialog::getSupportedServiceNames() + throw ( uno::RuntimeException ) + { + return impl_staticGetSupportedServiceNames(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/instancelocker.cxx b/comphelper/source/misc/instancelocker.cxx new file mode 100644 index 000000000000..d45671a9e151 --- /dev/null +++ b/comphelper/source/misc/instancelocker.cxx @@ -0,0 +1,515 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper_module.hxx" + +#include <com/sun/star/util/XCloseBroadcaster.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/DoubleInitializationException.hpp> +#include <com/sun/star/frame/DoubleInitializationException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include "instancelocker.hxx" + +using namespace ::com::sun::star; + + +// ==================================================================== +// OInstanceLocker +// ==================================================================== + +// -------------------------------------------------------- +OInstanceLocker::OInstanceLocker( const uno::Reference< uno::XComponentContext >& xContext ) +: m_xContext( xContext ) +, m_pLockListener( NULL ) +, m_pListenersContainer( NULL ) +, m_bDisposed( sal_False ) +, m_bInitialized( sal_False ) +{ +} + +// -------------------------------------------------------- +OInstanceLocker::~OInstanceLocker() +{ + if ( !m_bDisposed ) + { + m_refCount++; // to call dispose + try { + dispose(); + } + catch ( uno::RuntimeException& ) + {} + } + + if ( m_pListenersContainer ) + { + delete m_pListenersContainer; + m_pListenersContainer = NULL; + } +} + +// XComponent +// -------------------------------------------------------- +void SAL_CALL OInstanceLocker::dispose() + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); + if ( m_pListenersContainer ) + m_pListenersContainer->disposeAndClear( aSource ); + + if ( m_xLockListener.is() ) + { + if ( m_pLockListener ) + { + m_pLockListener->Dispose(); + m_pLockListener = NULL; + } + m_xLockListener = uno::Reference< uno::XInterface >(); + } + + m_bDisposed = sal_True; +} + +// -------------------------------------------------------- +void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pListenersContainer ) + m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex ); + + m_pListenersContainer->addInterface( xListener ); +} + +// -------------------------------------------------------- +void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_pListenersContainer ) + m_pListenersContainer->removeInterface( xListener ); +} + +// XInitialization +// -------------------------------------------------------- +void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments ) + throw (uno::Exception, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bInitialized ) + throw frame::DoubleInitializationException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_refCount ) + throw uno::RuntimeException(); // the object must be refcounted already! + + uno::Reference< uno::XInterface > xInstance; + uno::Reference< embed::XActionsApproval > xApproval; + sal_Int32 nModes = 0; + + try + { + sal_Int32 nLen = aArguments.getLength(); + if ( nLen < 2 || nLen > 3 ) + throw lang::IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong count of parameters!" ) ), + uno::Reference< uno::XInterface >(), + 0 ); + + if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() ) + throw lang::IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonempty reference is expected as the first argument!" ) ), + uno::Reference< uno::XInterface >(), + 0 ); + + if ( + !( aArguments[1] >>= nModes ) || + ( + !( nModes & embed::Actions::PREVENT_CLOSE ) && + !( nModes & embed::Actions::PREVENT_TERMINATION ) + ) + ) + { + throw lang::IllegalArgumentException( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("The correct modes set is expected as the second argument!" ) ), + uno::Reference< uno::XInterface >(), + 0 ); + } + + if ( nLen == 3 && !( aArguments[2] >>= xApproval ) ) + throw lang::IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("If the third argument is provided, it must be XActionsApproval implementation!" ) ), + uno::Reference< uno::XInterface >(), + 0 ); + + m_pLockListener = new OLockListener( uno::Reference< lang::XComponent > ( static_cast< lang::XComponent* >( this ) ), + xInstance, + nModes, + xApproval ); + m_xLockListener = uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( m_pLockListener ) ); + m_pLockListener->Init(); + } + catch( uno::Exception& ) + { + dispose(); + throw; + } + + m_bInitialized = sal_True; +} + + +// XServiceInfo +// -------------------------------------------------------- +::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName( ) + throw (uno::RuntimeException) +{ + return getImplementationName_static(); +} + +// -------------------------------------------------------- +::sal_Bool SAL_CALL OInstanceLocker::supportsService( const ::rtl::OUString& ServiceName ) + throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aSeq = getSupportedServiceNames(); + + for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) + if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) + return sal_True; + + return sal_False; +} + +// -------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames() + throw (uno::RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +// Static methods +// -------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames_static() +{ + const rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.InstanceLocker" ) ); + return uno::Sequence< rtl::OUString >( &aServiceName, 1 ); +} + +// -------------------------------------------------------- +::rtl::OUString SAL_CALL OInstanceLocker::getImplementationName_static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.embed.InstanceLocker" ) ); +} + +// -------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OInstanceLocker::Create( + const uno::Reference< uno::XComponentContext >& rxContext ) +{ + return static_cast< cppu::OWeakObject * >( new OInstanceLocker( rxContext ) ); +} + + + +// ==================================================================== +// OLockListener +// ==================================================================== + +// -------------------------------------------------------- +OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper, + const uno::Reference< uno::XInterface >& xInstance, + sal_Int32 nMode, + const uno::Reference< embed::XActionsApproval > xApproval ) +: m_xInstance( xInstance ) +, m_xApproval( xApproval ) +, m_xWrapper( xWrapper ) +, m_bDisposed( sal_False ) +, m_bInitialized( sal_False ) +, m_nMode( nMode ) +{ +} + +// -------------------------------------------------------- +OLockListener::~OLockListener() +{ +} + +// -------------------------------------------------------- +void OLockListener::Dispose() +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + return; + + if ( m_nMode & embed::Actions::PREVENT_CLOSE ) + { + try + { + uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY ); + if ( xCloseBroadcaster.is() ) + xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) ); + + uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY ); + if ( xCloseable.is() ) + xCloseable->close( sal_True ); + } + catch( uno::Exception& ) + {} + } + + if ( m_nMode & embed::Actions::PREVENT_TERMINATION ) + { + try + { + uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW ); + xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); + } + catch( uno::Exception& ) + {} + } + + m_xInstance = uno::Reference< uno::XInterface >(); + m_bDisposed = sal_True; +} + +// XEventListener +// -------------------------------------------------------- +void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + // object is disposed + if ( aEvent.Source == m_xInstance ) + { + // the object does not listen for anything any more + m_nMode = 0; + + // dispose the wrapper; + uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); + aGuard.clear(); + if ( xComponent.is() ) + { + try { xComponent->dispose(); } + catch( uno::Exception& ){} + } + } +} + + +// XCloseListener +// -------------------------------------------------------- +void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool ) + throw (util::CloseVetoException, uno::RuntimeException) +{ + // GetsOwnership parameter is always ignored, the user of the service must close the object always + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( !m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE ) ) + { + try + { + uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; + + // unlock the mutex here + aGuard.clear(); + + if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) ) + throw util::CloseVetoException(); + } + catch( util::CloseVetoException& ) + { + // rethrow this exception + throw; + } + catch( uno::Exception& ) + { + // no action should be done + } + } +} + +// -------------------------------------------------------- +void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + // object is closed, no reason to listen + if ( aEvent.Source == m_xInstance ) + { + uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( aEvent.Source, uno::UNO_QUERY ); + if ( xCloseBroadcaster.is() ) + { + xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) ); + m_nMode &= ~embed::Actions::PREVENT_CLOSE; + if ( !m_nMode ) + { + // dispose the wrapper; + uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); + aGuard.clear(); + if ( xComponent.is() ) + { + try { xComponent->dispose(); } + catch( uno::Exception& ){} + } + } + } + } +} + + +// XTerminateListener +// -------------------------------------------------------- +void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) + throw (frame::TerminationVetoException, uno::RuntimeException) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION ) ) + { + try + { + uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; + + // unlock the mutex here + aGuard.clear(); + + if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) ) + throw frame::TerminationVetoException(); + } + catch( frame::TerminationVetoException& ) + { + // rethrow this exception + throw; + } + catch( uno::Exception& ) + { + // no action should be done + } + } +} + +// -------------------------------------------------------- +void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + // object is terminated, no reason to listen + if ( aEvent.Source == m_xInstance ) + { + uno::Reference< frame::XDesktop > xDesktop( aEvent.Source, uno::UNO_QUERY ); + if ( xDesktop.is() ) + { + try + { + xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); + m_nMode &= ~embed::Actions::PREVENT_TERMINATION; + if ( !m_nMode ) + { + // dispose the wrapper; + uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); + aGuard.clear(); + if ( xComponent.is() ) + { + try { xComponent->dispose(); } + catch( uno::Exception& ){} + } + } + } + catch( uno::Exception& ) + {} + } + } +} + + +// XInitialization +// -------------------------------------------------------- +sal_Bool OLockListener::Init() +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed || m_bInitialized ) + return sal_False; + + try + { + if ( m_nMode & embed::Actions::PREVENT_CLOSE ) + { + uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY_THROW ); + xCloseBroadcaster->addCloseListener( static_cast< util::XCloseListener* >( this ) ); + } + + if ( m_nMode & embed::Actions::PREVENT_TERMINATION ) + { + uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW ); + xDesktop->addTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); + } + } + catch( uno::Exception& ) + { + // dispose the wrapper; + uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); + aGuard.clear(); + if ( xComponent.is() ) + { + try { xComponent->dispose(); } + catch( uno::Exception& ){} + } + + throw; + } + + m_bInitialized = sal_True; + + return sal_True; +} + +void createRegistryInfo_OInstanceLocker() +{ + static ::comphelper::module::OAutoRegistration< OInstanceLocker > aAutoRegistration; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/instancelocker.hxx b/comphelper/source/misc/instancelocker.hxx new file mode 100644 index 000000000000..e271bc2c94ba --- /dev/null +++ b/comphelper/source/misc/instancelocker.hxx @@ -0,0 +1,135 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __INSTANCELOCKER_HXX_ +#define __INSTANCELOCKER_HXX_ + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/util/XCloseListener.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/embed/XActionsApproval.hpp> +#include <com/sun/star/embed/Actions.hpp> +#include <cppuhelper/weakref.hxx> +#include <osl/mutex.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/interfacecontainer.h> + + +class OLockListener; + +// the service is implemented as a wrapper to be able to die by refcount +// the disposing mechanics is required for java related scenarios +class OInstanceLocker : public ::cppu::WeakImplHelper3< ::com::sun::star::lang::XComponent, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::lang::XServiceInfo > +{ + ::osl::Mutex m_aMutex; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xLockListener; + OLockListener* m_pLockListener; + + ::cppu::OInterfaceContainerHelper* m_pListenersContainer; // list of listeners + + sal_Bool m_bDisposed; + sal_Bool m_bInitialized; + +public: + OInstanceLocker( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext ); + ~OInstanceLocker(); + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames_static(); + + static ::rtl::OUString SAL_CALL getImplementationName_static(); + + 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 >& rxContext ); + +// 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); + +// 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); + +// 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); + +}; + + +class OLockListener : public ::cppu::WeakImplHelper2< ::com::sun::star::util::XCloseListener, + ::com::sun::star::frame::XTerminateListener > +{ + ::osl::Mutex m_aMutex; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xInstance; + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XActionsApproval > m_xApproval; + + ::com::sun::star::uno::WeakReference< ::com::sun::star::lang::XComponent > m_xWrapper; + + sal_Bool m_bDisposed; + sal_Bool m_bInitialized; + + sal_Int32 m_nMode; + +public: + OLockListener( const ::com::sun::star::uno::WeakReference< ::com::sun::star::lang::XComponent >& xWrapper, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xInstance, + sal_Int32 nMode, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XActionsApproval > xApproval ); + + ~OLockListener(); + + sal_Bool Init(); + void Dispose(); + +// XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::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); + +// XTerminateListener + virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& Event ) throw (::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& Event ) throw (::com::sun::star::uno::RuntimeException); + +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/interaction.cxx b/comphelper/source/misc/interaction.cxx new file mode 100644 index 000000000000..caae6cda0bc3 --- /dev/null +++ b/comphelper/source/misc/interaction.cxx @@ -0,0 +1,101 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/interaction.hxx> +#include <osl/diagnose.h> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::task; + + //========================================================================= + //= OInteractionPassword + //========================================================================= + //-------------------------------------------------------------------- + void SAL_CALL OInteractionPassword::setPassword( const ::rtl::OUString& _Password ) throw (RuntimeException) + { + m_sPassword = _Password;; + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OInteractionPassword::getPassword( ) throw (RuntimeException) + { + return m_sPassword; + } + + //========================================================================= + //= OInteractionRequest + //========================================================================= + //------------------------------------------------------------------------- + OInteractionRequest::OInteractionRequest(const Any& _rRequestDescription) + :m_aRequest(_rRequestDescription) + { + } + + //------------------------------------------------------------------------- + void OInteractionRequest::addContinuation(const Reference< XInteractionContinuation >& _rxContinuation) + { + OSL_ENSURE(_rxContinuation.is(), "OInteractionRequest::addContinuation: invalid argument!"); + if (_rxContinuation.is()) + { + sal_Int32 nOldLen = m_aContinuations.getLength(); + m_aContinuations.realloc(nOldLen + 1); + m_aContinuations[nOldLen] = _rxContinuation; + } + } + + //------------------------------------------------------------------------- + void OInteractionRequest::clearContinuations() + { + m_aContinuations.realloc(0); + } + + //------------------------------------------------------------------------- + Any SAL_CALL OInteractionRequest::getRequest( ) throw(RuntimeException) + { + return m_aRequest; + } + + //------------------------------------------------------------------------- + Sequence< Reference< XInteractionContinuation > > SAL_CALL OInteractionRequest::getContinuations( ) throw(RuntimeException) + { + return m_aContinuations; + } + +//......................................................................... +} // namespace comphelper +//......................................................................... + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/legacysingletonfactory.cxx b/comphelper/source/misc/legacysingletonfactory.cxx new file mode 100644 index 000000000000..53b76c7d2f52 --- /dev/null +++ b/comphelper/source/misc/legacysingletonfactory.cxx @@ -0,0 +1,200 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/legacysingletonfactory.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase2.hxx> + +#include <algorithm> + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + /** === 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::lang::XSingleComponentFactory; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::lang::XServiceInfo; + using ::com::sun::star::lang::XInitialization; + /** === end UNO using === **/ + + //==================================================================== + //= LegacySingletonFactory + //==================================================================== + typedef ::cppu::WeakImplHelper2 < XServiceInfo + , XSingleComponentFactory + > LegacySingletonFactory_Base; + + class COMPHELPER_DLLPRIVATE LegacySingletonFactory : public LegacySingletonFactory_Base + { + public: + LegacySingletonFactory( + ::cppu::ComponentFactoryFunc _componentFactoryFunc, const ::rtl::OUString& _rImplementationName, + const Sequence< ::rtl::OUString >& _rServiceNames, rtl_ModuleCount* _pModCount + ); + + // 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); + + // XSingleComponentFactory + virtual Reference< XInterface > SAL_CALL createInstanceWithContext( const Reference< XComponentContext >& Context ) throw (Exception, RuntimeException); + virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext( const Sequence< Any >& Arguments, const Reference< XComponentContext >& Context ) throw (Exception, RuntimeException); + + protected: + ~LegacySingletonFactory(); + + private: + /** creates m_xInstance, returns whether it actually was created (<TRUE/>) or existed before (<FALSE/> + */ + bool impl_nts_ensureInstance( const Reference< XComponentContext >& _rxContext ); + + private: + ::osl::Mutex m_aMutex; + ::cppu::ComponentFactoryFunc m_componentFactoryFunc; + ::rtl::OUString m_sImplementationName; + Sequence< ::rtl::OUString > m_aServiceNames; + rtl_ModuleCount* m_pModuleCount; + Reference< XInterface > m_xTheInstance; + }; + + //-------------------------------------------------------------------- + LegacySingletonFactory::LegacySingletonFactory( ::cppu::ComponentFactoryFunc _componentFactoryFunc, const ::rtl::OUString& _rImplementationName, + const Sequence< ::rtl::OUString >& _rServiceNames, rtl_ModuleCount* _pModCount ) + :m_componentFactoryFunc ( _componentFactoryFunc ) + ,m_sImplementationName ( _rImplementationName ) + ,m_aServiceNames ( _rServiceNames ) + ,m_pModuleCount ( _pModCount ) + ,m_xTheInstance ( ) + { + if ( m_pModuleCount ) + m_pModuleCount->acquire( m_pModuleCount ); + } + + //-------------------------------------------------------------------- + LegacySingletonFactory::~LegacySingletonFactory() + { + if ( m_pModuleCount ) + m_pModuleCount->release( m_pModuleCount ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL LegacySingletonFactory::getImplementationName( ) throw (RuntimeException) + { + return m_sImplementationName; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL LegacySingletonFactory::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 LegacySingletonFactory::getSupportedServiceNames( ) throw (RuntimeException) + { + return m_aServiceNames; + } + + //-------------------------------------------------------------------- + bool LegacySingletonFactory::impl_nts_ensureInstance( const Reference< XComponentContext >& _rxContext ) + { + if ( m_xTheInstance.is() ) + return false; + + m_xTheInstance = (*m_componentFactoryFunc)( _rxContext ); + if ( !m_xTheInstance.is() ) + throw RuntimeException(); + + return true; // true -> "was newly created" + } + + //-------------------------------------------------------------------- + Reference< XInterface > SAL_CALL LegacySingletonFactory::createInstanceWithContext( const Reference< XComponentContext >& _rxContext ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_nts_ensureInstance( _rxContext ); + + return m_xTheInstance; + } + + //-------------------------------------------------------------------- + Reference< XInterface > SAL_CALL LegacySingletonFactory::createInstanceWithArgumentsAndContext( const Sequence< Any >& _rArguments, const Reference< XComponentContext >& _rxContext ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !impl_nts_ensureInstance( _rxContext ) ) + throw RuntimeException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Instance already created before, unable to initialize it." ) ), + *this + ); + + Reference< XInitialization > xInit( m_xTheInstance, UNO_QUERY_THROW ); + xInit->initialize( _rArguments ); + + return m_xTheInstance; + } + + //==================================================================== + //= createLegacySingletonFactory + //==================================================================== + Reference< XSingleComponentFactory > createLegacySingletonFactory( + ::cppu::ComponentFactoryFunc _componentFactoryFunc, const ::rtl::OUString& _rImplementationName, + const Sequence< ::rtl::OUString >& _rServiceNames, rtl_ModuleCount* _pModCount ) + { + return new LegacySingletonFactory( _componentFactoryFunc, _rImplementationName, _rServiceNames, _pModCount ); + } + + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/listenernotification.cxx b/comphelper/source/misc/listenernotification.cxx new file mode 100644 index 000000000000..23bf563993b2 --- /dev/null +++ b/comphelper/source/misc/listenernotification.cxx @@ -0,0 +1,129 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/listenernotification.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + + //==================================================================== + //= OListenerContainer + //==================================================================== + //-------------------------------------------------------------------- + OListenerContainer::OListenerContainer( ::osl::Mutex& _rMutex ) + :m_aListeners( _rMutex ) + { + } + + OListenerContainer::~OListenerContainer() {} + + //-------------------------------------------------------------------- + void OListenerContainer::impl_addListener( const Reference< XEventListener >& _rxListener ) + { + OSL_PRECOND( _rxListener.is(), "OListenerContainer::impl_addListener: a NULL listener?!" ); + if ( _rxListener.is() ) + m_aListeners.addInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void OListenerContainer::impl_removeListener( const Reference< XEventListener >& _rxListener ) + { +#if OSL_DEBUG_LEVEL > 0 + ::cppu::OInterfaceIteratorHelper aIter( m_aListeners ); + bool bFound = false; + while ( aIter.hasMoreElements() && !bFound ) + { + bFound = ( Reference< XInterface >( aIter.next() ) == _rxListener ); + } + OSL_ENSURE( bFound, "OListenerContainer::impl_removeListener: sure your listener handling is correct? The given listener is not registered!" ); +#endif + m_aListeners.removeInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void OListenerContainer::disposing( const EventObject& _rEventSource ) + { + m_aListeners.disposeAndClear( _rEventSource ); + } + + //-------------------------------------------------------------------- + void OListenerContainer::clear() + { + m_aListeners.clear(); + } + + //-------------------------------------------------------------------- + bool OListenerContainer::impl_notify( const EventObject& _rEvent ) SAL_THROW(( Exception )) + { + ::cppu::OInterfaceIteratorHelper aIter( m_aListeners ); + bool bCancelled = false; + while ( aIter.hasMoreElements() && !bCancelled ) + { + Reference< XEventListener > xListener( static_cast< XEventListener* >( aIter.next() ) ); + if ( !xListener.is() ) + continue; + + try + { + bCancelled = !implNotify( xListener, _rEvent ); + } + catch( const DisposedException& e ) + { + // DisposedExceptions from the listener might indicate a + // broken connection to a different environment. + + OSL_ENSURE( e.Context.is(), "OListenerContainer::impl_notify: caught dispose exception with empty Context field" ); + + // If the exception stems from the listener then remove it + // from the list of listeners. If the Context field of the + // exception is empty this is interpreted to indicate the + // listener as well. + if ( e.Context == xListener || !e.Context.is() ) + aIter.remove(); + } + } + + return !bCancelled; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/locale.cxx b/comphelper/source/misc/locale.cxx new file mode 100644 index 000000000000..e08f5aa57f8e --- /dev/null +++ b/comphelper/source/misc/locale.cxx @@ -0,0 +1,685 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/locale.hxx> + +//_______________________________________________ +// includes +#include <rtl/ustrbuf.hxx> + +//_______________________________________________ +// namespace + +namespace comphelper{ + +//----------------------------------------------- +const sal_Unicode Locale::SEPERATOR_LC = (sal_Unicode)'-'; +const sal_Unicode Locale::SEPERATOR_CV = (sal_Unicode)'_'; +const sal_Unicode Locale::SEPERATOR_CV_LINUX = (sal_Unicode)'.'; + +//----------------------------------------------- +const Locale Locale::X_DEFAULT() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("x")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("default"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::EN() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::EN_US() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("US"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::DE_DE() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("de")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DE"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::DE_CH() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("de")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CH"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::DE_AT() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("de")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AT"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::AR() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ar")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::CA() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ca")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::CS() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("cs")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::DA() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("da")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::EL() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("el")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::ES() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("es")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::FI() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("fi")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::FR() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("fr")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::HE() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("he")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::HI_IN() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("hi")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IN"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::HU() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("hu")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::IT() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("it")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::JA() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ja")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::KO() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ko")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::NL() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nl")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::PL() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("pl")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::PT() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("pt")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::PT_BR() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("pt")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BR"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::RU() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ru")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::SK() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sk")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::SL() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sl")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::SV() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sv")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::TH() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("th")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::TR() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("tr")), + ::rtl::OUString()); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::X_COMMENT() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("x")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("comment"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::X_TRANSLATE() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("x")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("translate"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::X_NOTRANSLATE() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("x")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("notranslate"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::ZH_CN() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("zh")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CN"))); + return aLocale; +} + +//----------------------------------------------- +const Locale Locale::ZH_TW() +{ + static Locale aLocale( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("zh")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TW"))); + return aLocale; +} + +//----------------------------------------------- +Locale::Locale(const ::rtl::OUString& sISO) + throw(Locale::MalFormedLocaleException) +{ + fromISO(sISO); +} + +//----------------------------------------------- +Locale::Locale(const ::rtl::OUString& sLanguage, + const ::rtl::OUString& sCountry , + const ::rtl::OUString& sVariant ) +{ + // Use set methods to check values too! + setLanguage(sLanguage); + setCountry (sCountry ); + setVariant (sVariant ); +} + +//----------------------------------------------- +Locale::Locale() +{ + // Initialize instance ... otherwhise user will + // may be get exceptions if he e.g. copy this instance ... + (*this) = X_NOTRANSLATE(); +} + +//----------------------------------------------- +Locale::Locale(const Locale& aCopy) +{ + (*this) = aCopy; // recycle assign operator +} + +//----------------------------------------------- +::rtl::OUString Locale::getLanguage() const +{ + return m_sLanguage; +} + +//----------------------------------------------- +::rtl::OUString Locale::getCountry() const +{ + return m_sCountry; +} + +//----------------------------------------------- +::rtl::OUString Locale::getVariant() const +{ + return m_sVariant; +} + +//----------------------------------------------- +void Locale::setLanguage(const ::rtl::OUString& sLanguage) +{ + m_sLanguage = sLanguage; +} + +//----------------------------------------------- +void Locale::setCountry(const ::rtl::OUString& sCountry) +{ + m_sCountry = sCountry; +} + +//----------------------------------------------- +void Locale::setVariant(const ::rtl::OUString& sVariant) +{ + m_sVariant = sVariant; +} + +//----------------------------------------------- +/* Attention: Use own interface methods to set the + different parts of this locale. Because the + check the incoming value and throw an exception + automaticly ... + */ +void Locale::fromISO(const ::rtl::OUString& sISO) + throw(Locale::MalFormedLocaleException) +{ + m_sLanguage = ::rtl::OUString(); + m_sCountry = ::rtl::OUString(); + m_sVariant = ::rtl::OUString(); + + ::rtl::OUString sParser(sISO); + sParser.trim(); + + sal_Int32 nStart = 0; + sal_Int32 nEnd = 0; + + // extract language part + nEnd = sParser.indexOf(SEPERATOR_LC, nStart); + if (nEnd<0) + { + setLanguage(sParser); + return; + } + setLanguage(sParser.copy(nStart, nEnd-nStart)); + nStart = nEnd+1; + + // extract country + nEnd = sParser.indexOf(SEPERATOR_CV, nStart); + if (nEnd<0) + nEnd = sParser.indexOf(SEPERATOR_CV_LINUX, nStart); + if (nEnd<0) + { + setCountry(sParser.copy(nStart, sParser.getLength()-nStart)); + return; + } + nStart = nEnd+1; + + // extract variant + setVariant(sParser.copy(nStart, sParser.getLength()-nStart)); +} + +//----------------------------------------------- +::rtl::OUString Locale::toISO() const +{ + ::rtl::OUStringBuffer sISO(64); + + sISO.append(m_sLanguage); + if (m_sCountry.getLength()) + { + sISO.append(SEPERATOR_LC); + sISO.append(m_sCountry); + + if (m_sVariant.getLength()) + { + sISO.append(SEPERATOR_CV); + sISO.append(m_sVariant); + } + } + + return sISO.makeStringAndClear(); +} + +//----------------------------------------------- +sal_Bool Locale::equals(const Locale& aComparable) const +{ + return ( + m_sLanguage.equals(aComparable.m_sLanguage) && + m_sCountry.equals (aComparable.m_sCountry ) && + m_sVariant.equals (aComparable.m_sVariant ) + ); +} + +//----------------------------------------------- +sal_Bool Locale::similar(const Locale& aComparable) const +{ + return (m_sLanguage.equals(aComparable.m_sLanguage)); +} + +//----------------------------------------------- +::std::vector< ::rtl::OUString >::const_iterator Locale::getFallback(const ::std::vector< ::rtl::OUString >& lISOList , + const ::rtl::OUString& sReferenceISO) + throw(Locale::MalFormedLocaleException) +{ + Locale aReference(sReferenceISO); + + // Note: The same language or "en"/"en-US" should be preferred as fallback. + // On the other side some localized variables doesnt use localzation in real. + // May be the use a "fix" value only ... marked as X-DEFAULT or X-NOTRANSLATE. + // At least it can be discussed, if any language is a valid fallback ... + // But in case some office functionality depends on that (that means real functionality instead + // of pure UI descriptions) we should do anything, so it can work. + + ::std::vector< ::rtl::OUString >::const_iterator pSimilar = lISOList.end(); + ::std::vector< ::rtl::OUString >::const_iterator pEN_US = lISOList.end(); + ::std::vector< ::rtl::OUString >::const_iterator pEN = lISOList.end(); + ::std::vector< ::rtl::OUString >::const_iterator pXDefault = lISOList.end(); + ::std::vector< ::rtl::OUString >::const_iterator pXNoTranslate = lISOList.end(); + ::std::vector< ::rtl::OUString >::const_iterator pAny = lISOList.end(); + + ::std::vector< ::rtl::OUString >::const_iterator pIt; + for ( pIt = lISOList.begin(); + pIt != lISOList.end() ; + ++pIt ) + { + Locale aCheck(*pIt); + // found Locale, which match with 100% => return it + if (aCheck.equals(aReference)) + return pIt; + + // found similar Locale => safe it as possible fallback + if ( + (pSimilar == lISOList.end()) && + (aCheck.similar(aReference)) + ) + { + pSimilar = pIt; + } + else + // found en-US => safe it as fallback + if ( + (pEN_US == lISOList.end()) && + (aCheck.equals(EN_US()) ) + ) + { + pEN_US = pIt; + } + else + // found en[-XX] => safe it as fallback + if ( + (pEN == lISOList.end() ) && + (aCheck.similar(EN_US())) + ) + { + pEN = pIt; + } + else + // found an explicit default value(!) => safe it as fallback + if ( + (pXDefault == lISOList.end()) && + (aCheck.equals(X_DEFAULT()) ) + ) + { + pXDefault = pIt; + } + else + // found an implicit default value(!) => safe it as fallback + if ( + (pXNoTranslate == lISOList.end()) && + (aCheck.equals(X_NOTRANSLATE()) ) + ) + { + pXNoTranslate = pIt; + } + else + // safe the first locale, which isn't an explicit fallback + // as "last possible fallback" + if (pAny == lISOList.end()) + pAny = pIt; + } + + if (pSimilar != lISOList.end()) + return pSimilar; + + if (pEN_US != lISOList.end()) + return pEN_US; + + if (pEN != lISOList.end()) + return pEN; + + if (pXDefault != lISOList.end()) + return pXDefault; + + if (pXNoTranslate != lISOList.end()) + return pXNoTranslate; + + if (pAny != lISOList.end()) + return pAny; + + return lISOList.end(); +} + +//----------------------------------------------- +sal_Bool Locale::getFallback(Locale& aLocale) +{ + // a) + // this was our last fallback! + // break any further calls to this method ... + if (aLocale.equals(X_NOTRANSLATE())) + return sal_False; + + // b) + // switch from X_DEFAULT to X_NOTRANSLATE + // next time we will go to a) + if (aLocale.equals(X_DEFAULT())) + { + aLocale = X_NOTRANSLATE(); + return sal_True; + } + + // c) + // switch from EN to X_DEFAULT + // next time we will go to b) + if (aLocale.equals(EN())) + { + aLocale = X_DEFAULT(); + return sal_True; + } + + // d) remove country from incoming locale + // e.g. "de-DE" => "de" or "en-US" => "en"! + if (aLocale.getCountry().getLength()) + { + aLocale.setCountry(::rtl::OUString()); + return sal_True; + } + + // e) "en-US" possible? + if (!aLocale.equals(EN_US())) + { + aLocale = EN_US(); + return sal_True; + } + + // f) no more fallbacks + return sal_False; +} + +//----------------------------------------------- +void Locale::operator=(const Locale& rCopy) +{ + // Take over these values without checking ... + // They was already checked if the copy was constructed + // and must be valid now! + m_sLanguage = rCopy.m_sLanguage; + m_sCountry = rCopy.m_sCountry; + m_sVariant = rCopy.m_sVariant; +} + +//----------------------------------------------- +sal_Bool Locale::operator==(const Locale& aComparable) const +{ + return equals(aComparable); +} + +//----------------------------------------------- +sal_Bool Locale::operator!=(const Locale& aComparable) const +{ + return !equals(aComparable); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/logging.cxx b/comphelper/source/misc/logging.cxx new file mode 100644 index 000000000000..f9467998c48c --- /dev/null +++ b/comphelper/source/misc/logging.cxx @@ -0,0 +1,408 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include <comphelper/logging.hxx> +#include <comphelper/componentcontext.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/logging/LoggerPool.hpp> +#include <com/sun/star/logging/LogLevel.hpp> +#include <com/sun/star/resource/XResourceBundle.hpp> +#include <com/sun/star/resource/XResourceBundleLoader.hpp> +/** === end UNO includes === **/ + +#include <rtl/ustrbuf.hxx> + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::logging::XLoggerPool; + using ::com::sun::star::logging::LoggerPool; + using ::com::sun::star::logging::XLogger; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::logging::XLogHandler; + using ::com::sun::star::resource::XResourceBundle; + using ::com::sun::star::resource::XResourceBundleLoader; + /** === end UNO using === **/ + namespace LogLevel = ::com::sun::star::logging::LogLevel; + + //==================================================================== + //= EventLogger_Impl - declaration + //==================================================================== + class EventLogger_Impl + { + private: + ::comphelper::ComponentContext m_aContext; + ::rtl::OUString m_sLoggerName; + Reference< XLogger > m_xLogger; + + public: + EventLogger_Impl( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rLoggerName ) + :m_aContext( _rxContext ) + ,m_sLoggerName( _rLoggerName ) + { + impl_createLogger_nothrow(); + } + + inline bool isValid() const { return m_xLogger.is(); } + inline const ::rtl::OUString& getName() const { return m_sLoggerName; } + inline const Reference< XLogger >& getLogger() const { return m_xLogger; } + inline const ::comphelper::ComponentContext& getContext() const { return m_aContext; } + + private: + void impl_createLogger_nothrow(); + }; + + //==================================================================== + //= EventLogger_Impl - implementation + //==================================================================== + //-------------------------------------------------------------------- + void EventLogger_Impl::impl_createLogger_nothrow() + { + try + { + Reference< XLoggerPool > xPool( LoggerPool::get( m_aContext.getUNOContext() ), UNO_QUERY_THROW ); + if ( m_sLoggerName.getLength() ) + m_xLogger = xPool->getNamedLogger( m_sLoggerName ); + else + m_xLogger = xPool->getDefaultLogger(); + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "EventLogger_Impl::impl_createLogger_nothrow: caught an exception!" ); + } + } + + //==================================================================== + //= EventLogger + //==================================================================== + //-------------------------------------------------------------------- + EventLogger::EventLogger( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rLoggerName ) + :m_pImpl( new EventLogger_Impl( _rxContext, _rLoggerName ) ) + { + } + + //-------------------------------------------------------------------- + EventLogger::EventLogger( const Reference< XComponentContext >& _rxContext, const sal_Char* _pAsciiLoggerName ) + :m_pImpl( new EventLogger_Impl( _rxContext, ::rtl::OUString::createFromAscii( _pAsciiLoggerName ) ) ) + { + } + + //-------------------------------------------------------------------- + EventLogger::~EventLogger() + { + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& EventLogger::getName() const + { + return m_pImpl->getName(); + } + + //-------------------------------------------------------------------- + sal_Int32 EventLogger::getLogLevel() const + { + try + { + if ( m_pImpl->isValid() ) + return m_pImpl->getLogger()->getLevel(); + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "EventLogger::getLogLevel: caught an exception!" ); + } + + return LogLevel::OFF; + } + + //-------------------------------------------------------------------- + void EventLogger::setLogLevel( const sal_Int32 _nLogLevel ) const + { + try + { + if ( m_pImpl->isValid() ) + m_pImpl->getLogger()->setLevel( _nLogLevel ); + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "EventLogger::setLogLevel: caught an exception!" ); + } + } + + //-------------------------------------------------------------------- + bool EventLogger::isLoggable( const sal_Int32 _nLogLevel ) const + { + if ( !m_pImpl->isValid() ) + return false; + + try + { + return m_pImpl->getLogger()->isLoggable( _nLogLevel ); + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "EventLogger::isLoggable: caught an exception!" ); + } + + return false; + } + + //-------------------------------------------------------------------- + bool EventLogger::addLogHandler( const Reference< XLogHandler >& _rxLogHandler ) + { + try + { + if ( m_pImpl->isValid() ) + { + m_pImpl->getLogger()->addLogHandler( _rxLogHandler ); + return true; + } + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "EventLogger::addLogHandler: caught an exception!" ); + } + return false; + } + + //-------------------------------------------------------------------- + bool EventLogger::removeLogHandler( const Reference< XLogHandler >& _rxLogHandler ) + { + try + { + if ( m_pImpl->isValid() ) + { + m_pImpl->getLogger()->removeLogHandler( _rxLogHandler ); + return true; + } + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "EventLogger::removeLogHandler: caught an exception!" ); + } + return false; + } + + //-------------------------------------------------------------------- + namespace + { + void lcl_replaceParameter( ::rtl::OUString& _inout_Message, const ::rtl::OUString& _rPlaceHolder, const ::rtl::OUString& _rReplacement ) + { + sal_Int32 nPlaceholderPosition = _inout_Message.indexOf( _rPlaceHolder ); + OSL_ENSURE( nPlaceholderPosition >= 0, "lcl_replaceParameter: placeholder not found!" ); + if ( nPlaceholderPosition < 0 ) + return; + + _inout_Message = _inout_Message.replaceAt( nPlaceholderPosition, _rPlaceHolder.getLength(), _rReplacement ); + } + } + + //-------------------------------------------------------------------- + bool EventLogger::impl_log( const sal_Int32 _nLogLevel, + const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, + const OptionalString& _rArgument1, const OptionalString& _rArgument2, + const OptionalString& _rArgument3, const OptionalString& _rArgument4, + const OptionalString& _rArgument5, const OptionalString& _rArgument6 ) const + { + // (if ::rtl::OUString had an indexOfAscii, we could save those ugly statics ...) + static ::rtl::OUString sPH1( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$1$" ) ) ); + static ::rtl::OUString sPH2( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$2$" ) ) ); + static ::rtl::OUString sPH3( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$3$" ) ) ); + static ::rtl::OUString sPH4( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$4$" ) ) ); + static ::rtl::OUString sPH5( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$5$" ) ) ); + static ::rtl::OUString sPH6( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$6$" ) ) ); + + ::rtl::OUString sMessage( _rMessage ); + if ( !!_rArgument1 ) + lcl_replaceParameter( sMessage, sPH1, *_rArgument1 ); + + if ( !!_rArgument2 ) + lcl_replaceParameter( sMessage, sPH2, *_rArgument2 ); + + if ( !!_rArgument3 ) + lcl_replaceParameter( sMessage, sPH3, *_rArgument3 ); + + if ( !!_rArgument4 ) + lcl_replaceParameter( sMessage, sPH4, *_rArgument4 ); + + if ( !!_rArgument5 ) + lcl_replaceParameter( sMessage, sPH5, *_rArgument5 ); + + if ( !!_rArgument6 ) + lcl_replaceParameter( sMessage, sPH6, *_rArgument6 ); + + try + { + Reference< XLogger > xLogger( m_pImpl->getLogger() ); + OSL_PRECOND( xLogger.is(), "EventLogger::impl_log: should never be called without a logger!" ); + if ( _pSourceClass && _pSourceMethod ) + { + xLogger->logp( + _nLogLevel, + ::rtl::OUString::createFromAscii( _pSourceClass ), + ::rtl::OUString::createFromAscii( _pSourceMethod ), + sMessage + ); + } + else + { + xLogger->log( _nLogLevel, sMessage ); + } + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "EventLogger::impl_log: caught an exception!" ); + } + + return false; + } + + //==================================================================== + //= ResourceBasedEventLogger_Data + //==================================================================== + struct ResourceBasedEventLogger_Data + { + /// the base name of the resource bundle + ::rtl::OUString sBundleBaseName; + /// did we already attempt to load the bundle? + bool bBundleLoaded; + /// the lazily loaded bundle + Reference< XResourceBundle > xBundle; + + ResourceBasedEventLogger_Data() + :sBundleBaseName() + ,bBundleLoaded( false ) + ,xBundle() + { + } + }; + + //-------------------------------------------------------------------- + bool lcl_loadBundle_nothrow( const ComponentContext& _rContext, ResourceBasedEventLogger_Data& _rLoggerData ) + { + if ( _rLoggerData.bBundleLoaded ) + return _rLoggerData.xBundle.is(); + + // no matter what happens below, don't attempt creation ever again + _rLoggerData.bBundleLoaded = true; + + try + { + Reference< XResourceBundleLoader > xLoader( _rContext.getSingleton( "com.sun.star.resource.OfficeResourceLoader" ), UNO_QUERY_THROW ); + _rLoggerData.xBundle = Reference< XResourceBundle >( xLoader->loadBundle_Default( _rLoggerData.sBundleBaseName ), UNO_QUERY_THROW ); + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "lcl_loadBundle_nothrow: caught an exception!" ); + } + + return _rLoggerData.xBundle.is(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString lcl_loadString_nothrow( const Reference< XResourceBundle >& _rxBundle, const sal_Int32 _nMessageResID ) + { + OSL_PRECOND( _rxBundle.is(), "lcl_loadString_nothrow: this will crash!" ); + ::rtl::OUString sMessage; + try + { + ::rtl::OUStringBuffer aBuffer; + aBuffer.appendAscii( "string:" ); + aBuffer.append( _nMessageResID ); + OSL_VERIFY( _rxBundle->getDirectElement( aBuffer.makeStringAndClear() ) >>= sMessage ); + } + catch( const Exception& e ) + { + (void)e; + OSL_ENSURE( false, "lcl_loadString_nothrow: caught an exception!" ); + } + return sMessage; + } + + //==================================================================== + //= ResourceBasedEventLogger + //==================================================================== + //-------------------------------------------------------------------- + ResourceBasedEventLogger::ResourceBasedEventLogger( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rResourceBundleBaseName, + const ::rtl::OUString& _rLoggerName ) + :EventLogger( _rxContext, _rLoggerName ) + ,m_pData( new ResourceBasedEventLogger_Data ) + { + m_pData->sBundleBaseName = _rResourceBundleBaseName; + } + + //-------------------------------------------------------------------- + ResourceBasedEventLogger::ResourceBasedEventLogger( const Reference< XComponentContext >& _rxContext, const sal_Char* _pResourceBundleBaseName, + const sal_Char* _pAsciiLoggerName ) + :EventLogger( _rxContext, _pAsciiLoggerName ) + ,m_pData( new ResourceBasedEventLogger_Data ) + { + m_pData->sBundleBaseName = ::rtl::OUString::createFromAscii( _pResourceBundleBaseName ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString ResourceBasedEventLogger::impl_loadStringMessage_nothrow( const sal_Int32 _nMessageResID ) const + { + ::rtl::OUString sMessage; + if ( lcl_loadBundle_nothrow( m_pImpl->getContext(), *m_pData ) ) + sMessage = lcl_loadString_nothrow( m_pData->xBundle, _nMessageResID ); + if ( sMessage.getLength() == 0 ) + { + ::rtl::OUStringBuffer aBuffer; + aBuffer.appendAscii( "<invalid event resource: '" ); + aBuffer.append( m_pData->sBundleBaseName ); + aBuffer.appendAscii( ":" ); + aBuffer.append( _nMessageResID ); + aBuffer.appendAscii( "'>" ); + sMessage = aBuffer.makeStringAndClear(); + } + return sMessage; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/makefile.mk b/comphelper/source/misc/makefile.mk new file mode 100644 index 000000000000..cecba554b332 --- /dev/null +++ b/comphelper/source/misc/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=comphelper +TARGET=misc + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/accessiblecomponenthelper.obj \ + $(SLO)$/accessiblecontexthelper.obj \ + $(SLO)$/accessibleeventbuffer.obj \ + $(SLO)$/accessibleeventnotifier.obj \ + $(SLO)$/accessiblekeybindinghelper.obj \ + $(SLO)$/accessibleselectionhelper.obj \ + $(SLO)$/accessibletexthelper.obj \ + $(SLO)$/accessiblewrapper.obj \ + $(SLO)$/accimplaccess.obj \ + $(SLO)$/anytostring.obj \ + $(SLO)$/asyncnotification.obj \ + $(SLO)$/componentcontext.obj \ + $(SLO)$/componentmodule.obj \ + $(SLO)$/configurationhelper.obj \ + $(SLO)$/docpasswordhelper.obj \ + $(SLO)$/docpasswordrequest.obj \ + $(SLO)$/documentinfo.obj \ + $(SLO)$/evtmethodhelper.obj \ + $(SLO)$/documentiologring.obj \ + $(SLO)$/evtlistenerhlp.obj \ + $(SLO)$/ihwrapnofilter.obj \ + $(SLO)$/instancelocker.obj \ + $(SLO)$/interaction.obj \ + $(SLO)$/legacysingletonfactory.obj \ + $(SLO)$/listenernotification.obj \ + $(SLO)$/locale.obj \ + $(SLO)$/logging.obj \ + $(SLO)$/mediadescriptor.obj \ + $(SLO)$/mimeconfighelper.obj \ + $(SLO)$/namedvaluecollection.obj \ + $(SLO)$/numberedcollection.obj \ + $(SLO)$/numbers.obj \ + $(SLO)$/officeresourcebundle.obj \ + $(SLO)$/officerestartmanager.obj \ + $(SLO)$/proxyaggregation.obj \ + $(SLO)$/querydeep.obj \ + $(SLO)$/regpathhelper.obj \ + $(SLO)$/scopeguard.obj \ + $(SLO)$/SelectionMultiplex.obj \ + $(SLO)$/sequenceashashmap.obj \ + $(SLO)$/sequence.obj \ + $(SLO)$/servicedecl.obj \ + $(SLO)$/serviceinfohelper.obj \ + $(SLO)$/sharedmutex.obj \ + $(SLO)$/synchronousdispatch.obj \ + $(SLO)$/storagehelper.obj \ + $(SLO)$/string.obj \ + $(SLO)$/types.obj \ + $(SLO)$/uieventslogger.obj \ + $(SLO)$/weakeventlistener.obj \ + $(SLO)$/weak.obj \ + $(SLO)$/comphelper_module.obj \ + $(SLO)$/comphelper_services.obj \ + $(SLO)$/componentbase.obj \ + $(SLO)$/stillreadwriteinteraction.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/comphelper/source/misc/mediadescriptor.cxx b/comphelper/source/misc/mediadescriptor.cxx new file mode 100644 index 000000000000..d7bc4deb961e --- /dev/null +++ b/comphelper/source/misc/mediadescriptor.cxx @@ -0,0 +1,870 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/mediadescriptor.hxx> +#include <comphelper/stillreadwriteinteraction.hxx> + +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XUriReference.hpp> +#include <com/sun/star/ucb/PostCommandArgument2.hpp> +#include <com/sun/star/container/XNameAccess.hpp> + +#include <ucbhelper/interceptedinteraction.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/commandenvironment.hxx> +#include <ucbhelper/activedatasink.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/configurationhelper.hxx> + +#include <rtl/ustrbuf.hxx> + +//_______________________________________________ +// namespace + +namespace comphelper{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 10.03.2004 07:35 +-----------------------------------------------*/ +const ::rtl::OUString& MediaDescriptor::PROP_ABORTED() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Aborted")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_ASTEMPLATE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("AsTemplate")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_CHARACTERSET() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("CharacterSet")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_COMPONENTDATA() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ComponentData")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_DEEPDETECTION() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DeepDetection")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_DETECTSERVICE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DetectService")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_DOCUMENTSERVICE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DocumentService")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_EXTENSION() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Extension")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_FILENAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FileName")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_FILTERNAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FilterName")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_FILTEROPTIONS() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FilterOptions")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_FORMAT() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Format")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_FRAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Frame")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_FRAMENAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("FrameName")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_HIDDEN() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Hidden")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_INPUTSTREAM() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("InputStream")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_INTERACTIONHANDLER() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("InteractionHandler")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_JUMPMARK() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("JumpMark")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_MACROEXECUTIONMODE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("MacroExecutionMode")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_MEDIATYPE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("MediaType")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_MINIMIZED() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Minimized")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_NOAUTOSAVE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("NoAutoSave")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_OPENNEWVIEW() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("OpenNewView")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_OUTPUTSTREAM() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("OutputStream")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_PATTERN() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Pattern")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_POSSIZE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("PosSize")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_POSTDATA() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("PostData")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_POSTSTRING() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("PostString")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_PREVIEW() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Preview")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_READONLY() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_REFERRER() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Referer")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_SILENT() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Silent")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_STATUSINDICATOR() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("StatusIndicator")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_STREAM() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Stream")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_STREAMFOROUTPUT() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("StreamForOutput")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_TEMPLATENAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("TemplateName")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_TEMPLATEREGIONNAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("TemplateRegionName")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_TYPENAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_UCBCONTENT() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("UCBContent")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_UPDATEDOCMODE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("UpdateDocMode")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_URL() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("URL")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_VERSION() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Version")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_VIEWID() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ViewId")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_REPAIRPACKAGE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("RepairPackage")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_DOCUMENTTITLE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_MODEL() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Model")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_PASSWORD() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Password")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_TITLE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("Title")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_SALVAGEDFILE() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("SalvagedFile")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_VIEWONLY() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ViewOnly")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_DOCUMENTBASEURL() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("DocumentBaseURL")); + return sProp; +} + +const ::rtl::OUString& MediaDescriptor::PROP_VIEWCONTROLLERNAME() +{ + static const ::rtl::OUString sProp(RTL_CONSTASCII_USTRINGPARAM("ViewControllerName")); + return sProp; +} +/*----------------------------------------------- + 10.03.2004 08:09 +-----------------------------------------------*/ +MediaDescriptor::MediaDescriptor() + : SequenceAsHashMap() +{ +} + +/*----------------------------------------------- + 10.03.2004 08:09 +-----------------------------------------------*/ +MediaDescriptor::MediaDescriptor(const css::uno::Any& aSource) + : SequenceAsHashMap(aSource) +{ +} + +/*----------------------------------------------- + 10.03.2004 08:09 +-----------------------------------------------*/ +MediaDescriptor::MediaDescriptor(const css::uno::Sequence< css::beans::PropertyValue >& lSource) + : SequenceAsHashMap(lSource) +{ +} + +/*----------------------------------------------- + 10.03.2004 08:09 +-----------------------------------------------*/ +MediaDescriptor::MediaDescriptor(const css::uno::Sequence< css::beans::NamedValue >& lSource) + : SequenceAsHashMap(lSource) +{ +} + +/*----------------------------------------------- + 18.11.2004 13:37 +-----------------------------------------------*/ +sal_Bool MediaDescriptor::isStreamReadOnly() const +{ + static ::rtl::OUString CONTENTSCHEME_FILE = ::rtl::OUString::createFromAscii("file"); + static ::rtl::OUString CONTENTPROP_ISREADONLY = ::rtl::OUString::createFromAscii("IsReadOnly"); + static sal_Bool READONLY_FALLBACK = sal_False; + + sal_Bool bReadOnly = READONLY_FALLBACK; + + // check for explicit readonly state + const_iterator pIt = find(MediaDescriptor::PROP_READONLY()); + if (pIt != end()) + { + pIt->second >>= bReadOnly; + return bReadOnly; + } + + // streams based on post data are readonly by definition + pIt = find(MediaDescriptor::PROP_POSTDATA()); + if (pIt != end()) + return sal_True; + + // A XStream capsulate XInputStream and XOutputStream ... + // If it exists - the file must be open in read/write mode! + pIt = find(MediaDescriptor::PROP_STREAM()); + if (pIt != end()) + return sal_False; + + // Only file system content provider is able to provide XStream + // so for this content impossibility to create XStream triggers + // switch to readonly mode. + try + { + css::uno::Reference< css::ucb::XContent > xContent = getUnpackedValueOrDefault(MediaDescriptor::PROP_UCBCONTENT(), css::uno::Reference< css::ucb::XContent >()); + if (xContent.is()) + { + css::uno::Reference< css::ucb::XContentIdentifier > xId(xContent->getIdentifier(), css::uno::UNO_QUERY); + ::rtl::OUString aScheme; + if (xId.is()) + aScheme = xId->getContentProviderScheme(); + + if (aScheme.equalsIgnoreAsciiCase(CONTENTSCHEME_FILE)) + bReadOnly = sal_True; + else + { + ::ucbhelper::Content aContent(xContent, css::uno::Reference< css::ucb::XCommandEnvironment >()); + aContent.getPropertyValue(CONTENTPROP_ISREADONLY) >>= bReadOnly; + } + } + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} + + return bReadOnly; +} + +// ---------------------------------------------------------------------------- + +css::uno::Any MediaDescriptor::getComponentDataEntry( const ::rtl::OUString& rName ) const +{ + SequenceAsHashMap aCompDataMap( getUnpackedValueOrDefault( PROP_COMPONENTDATA(), ComponentDataSequence() ) ); + SequenceAsHashMap::iterator aIt = aCompDataMap.find( rName ); + return (aIt == aCompDataMap.end()) ? css::uno::Any() : aIt->second; +} + +void MediaDescriptor::setComponentDataEntry( const ::rtl::OUString& rName, const css::uno::Any& rValue ) +{ + if( rValue.hasValue() ) + { + // get or craete the 'ComponentData' property entry + css::uno::Any& rCompDataAny = operator[]( PROP_COMPONENTDATA() ); + // check type, insert the value + OSL_ENSURE( !rCompDataAny.hasValue() || rCompDataAny.has< ComponentDataSequence >(), + "MediaDescriptor::setComponentDataEntry - incompatible 'ComponentData' property in media descriptor" ); + if( !rCompDataAny.hasValue() || rCompDataAny.has< ComponentDataSequence >() ) + { + // insert or overwrite the passed value + SequenceAsHashMap aCompDataMap( rCompDataAny ); + aCompDataMap[ rName ] = rValue; + // write back the sequence (sal_False = use NamedValue instead of PropertyValue) + rCompDataAny = aCompDataMap.getAsConstAny( sal_False ); + } + } + else + { + // if an empty Any is passed, clear the entry + clearComponentDataEntry( rName ); + } +} + +void MediaDescriptor::clearComponentDataEntry( const ::rtl::OUString& rName ) +{ + SequenceAsHashMap::iterator aPropertyIter = find( PROP_COMPONENTDATA() ); + if( aPropertyIter != end() ) + { + OSL_ENSURE( aPropertyIter->second.has< ComponentDataSequence >(), + "MediaDescriptor::clearComponentDataEntry - incompatible 'ComponentData' property in media descriptor" ); + if( aPropertyIter->second.has< ComponentDataSequence >() ) + { + // remove the value with the passed name + SequenceAsHashMap aCompDataMap( aPropertyIter->second ); + aCompDataMap.erase( rName ); + // write back the sequence, or remove it completely if it is empty + if( aCompDataMap.empty() ) + erase( aPropertyIter ); + else + aPropertyIter->second = aCompDataMap.getAsConstAny( sal_False ); + } + } +} + +/*----------------------------------------------- + 10.03.2004 09:02 +-----------------------------------------------*/ +sal_Bool MediaDescriptor::addInputStream() +{ + return impl_addInputStream( sal_True ); +} + +/*-----------------------------------------------*/ +sal_Bool MediaDescriptor::addInputStreamOwnLock() +{ + // Own lock file implementation + + sal_Bool bUseLock = sal_True; // the system file locking is used per default + try + { + + css::uno::Reference< css::uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig( + ::comphelper::getProcessServiceFactory(), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ), + ::comphelper::ConfigurationHelper::E_STANDARD ); + if ( !xCommonConfig.is() ) + throw css::uno::RuntimeException(); + + ::comphelper::ConfigurationHelper::readRelativeKey( + xCommonConfig, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentSystemFileLocking" ) ) ) >>= bUseLock; + } + catch( const css::uno::Exception& ) + { + } + + return impl_addInputStream( bUseLock ); +} + +/*-----------------------------------------------*/ +sal_Bool MediaDescriptor::impl_addInputStream( sal_Bool bLockFile ) +{ + // check for an already existing stream item first + const_iterator pIt = find(MediaDescriptor::PROP_INPUTSTREAM()); + if (pIt != end()) + return sal_True; + + try + { + // No stream available - create a new one + // a) data comes as PostData ... + pIt = find(MediaDescriptor::PROP_POSTDATA()); + if (pIt != end()) + { + const css::uno::Any& rPostData = pIt->second; + css::uno::Reference< css::io::XInputStream > xPostData; + rPostData >>= xPostData; + + return impl_openStreamWithPostData( xPostData ); + } + + // b) ... or we must get it from the given URL + ::rtl::OUString sURL = getUnpackedValueOrDefault(MediaDescriptor::PROP_URL(), ::rtl::OUString()); + if (!sURL.getLength()) + throw css::uno::Exception( + ::rtl::OUString::createFromAscii("Found no URL."), + css::uno::Reference< css::uno::XInterface >()); + + // Parse URL! Only the main part has to be used further. E.g. a jumpmark can make trouble + ::rtl::OUString sNormalizedURL = impl_normalizeURL( sURL ); + return impl_openStreamWithURL( sNormalizedURL, bLockFile ); + } +#if OSL_DEBUG_LEVEL>0 + catch(const css::uno::Exception& ex) + { + ::rtl::OUStringBuffer sMsg(256); + sMsg.appendAscii("Invalid MediaDescriptor detected:\n"); + sMsg.append (ex.Message ); + OSL_ENSURE(sal_False, ::rtl::OUStringToOString(sMsg.makeStringAndClear(), RTL_TEXTENCODING_UTF8).getStr()); + } +#else + catch(const css::uno::Exception&) + {} +#endif + + return sal_False; +} + +/*----------------------------------------------- + 25.03.2004 12:38 +-----------------------------------------------*/ +sal_Bool MediaDescriptor::impl_openStreamWithPostData( const css::uno::Reference< css::io::XInputStream >& _rxPostData ) + throw(::com::sun::star::uno::RuntimeException) +{ + if ( !_rxPostData.is() ) + throw css::lang::IllegalArgumentException( + ::rtl::OUString::createFromAscii("Found invalid PostData."), + css::uno::Reference< css::uno::XInterface >(), 1); + + // PostData can't be used in read/write mode! + (*this)[MediaDescriptor::PROP_READONLY()] <<= sal_True; + + // prepare the environment + css::uno::Reference< css::task::XInteractionHandler > xInteraction = getUnpackedValueOrDefault( + MediaDescriptor::PROP_INTERACTIONHANDLER(), + css::uno::Reference< css::task::XInteractionHandler >()); + css::uno::Reference< css::ucb::XProgressHandler > xProgress; + ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress); + css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY); + + // media type + ::rtl::OUString sMediaType = getUnpackedValueOrDefault(MediaDescriptor::PROP_MEDIATYPE(), ::rtl::OUString()); + if (!sMediaType.getLength()) + { + sMediaType = ::rtl::OUString::createFromAscii("application/x-www-form-urlencoded"); + (*this)[MediaDescriptor::PROP_MEDIATYPE()] <<= sMediaType; + } + + // url + ::rtl::OUString sURL( getUnpackedValueOrDefault( PROP_URL(), ::rtl::OUString() ) ); + + css::uno::Reference< css::io::XInputStream > xResultStream; + try + { + // seek PostData stream to the beginning + css::uno::Reference< css::io::XSeekable > xSeek( _rxPostData, css::uno::UNO_QUERY ); + if ( xSeek.is() ) + xSeek->seek( 0 ); + + // a content for the URL + ::ucbhelper::Content aContent( sURL, xCommandEnv ); + + // use post command + css::ucb::PostCommandArgument2 aPostArgument; + aPostArgument.Source = _rxPostData; + css::uno::Reference< css::io::XActiveDataSink > xSink( new ucbhelper::ActiveDataSink ); + aPostArgument.Sink = xSink; + aPostArgument.MediaType = sMediaType; + aPostArgument.Referer = getUnpackedValueOrDefault( PROP_REFERRER(), ::rtl::OUString() ); + + ::rtl::OUString sCommandName( RTL_CONSTASCII_USTRINGPARAM( "post" ) ); + aContent.executeCommand( sCommandName, css::uno::makeAny( aPostArgument ) ); + + // get result + xResultStream = xSink->getInputStream(); + } + catch( const css::uno::Exception& ) + { + } + + // success? + if ( !xResultStream.is() ) + { + OSL_ENSURE( false, "no valid reply to the HTTP-Post" ); + return sal_False; + } + + (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xResultStream; + return sal_True; +} + +/*-----------------------------------------------*/ + +/*----------------------------------------------- + 25.03.2004 12:29 +-----------------------------------------------*/ +sal_Bool MediaDescriptor::impl_openStreamWithURL( const ::rtl::OUString& sURL, sal_Bool bLockFile ) + throw(::com::sun::star::uno::RuntimeException) +{ + // prepare the environment + css::uno::Reference< css::task::XInteractionHandler > xOrgInteraction = getUnpackedValueOrDefault( + MediaDescriptor::PROP_INTERACTIONHANDLER(), + css::uno::Reference< css::task::XInteractionHandler >()); + + StillReadWriteInteraction* pInteraction = new StillReadWriteInteraction(xOrgInteraction); + css::uno::Reference< css::task::XInteractionHandler > xInteraction(static_cast< css::task::XInteractionHandler* >(pInteraction), css::uno::UNO_QUERY); + + css::uno::Reference< css::ucb::XProgressHandler > xProgress; + ::ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment(xInteraction, xProgress); + css::uno::Reference< css::ucb::XCommandEnvironment > xCommandEnv(static_cast< css::ucb::XCommandEnvironment* >(pCommandEnv), css::uno::UNO_QUERY); + + // try to create the content + // no content -> no stream => return immediatly with FALSE + ::ucbhelper::Content aContent; + css::uno::Reference< css::ucb::XContent > xContent; + try + { + aContent = ::ucbhelper::Content(sURL, xCommandEnv); + xContent = aContent.get(); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::ucb::ContentCreationException&) + { return sal_False; } // TODO error handling + catch(const css::uno::Exception&) + { return sal_False; } // TODO error handling + + // try to open the file in read/write mode + // (if its allowed to do so). + // But handle errors in a "hidden mode". Because + // we try it readonly later - if read/write isnt an option. + css::uno::Reference< css::io::XStream > xStream ; + css::uno::Reference< css::io::XInputStream > xInputStream; + + sal_Bool bReadOnly = sal_False; + sal_Bool bModeRequestedExplicitly = sal_False; + const_iterator pIt = find(MediaDescriptor::PROP_READONLY()); + if (pIt != end()) + { + pIt->second >>= bReadOnly; + bModeRequestedExplicitly = sal_True; + } + + if ( !bReadOnly && bLockFile ) + { + try + { + // TODO: use "special" still interaction to supress error messages + xStream = aContent.openWriteableStream(); + if (xStream.is()) + xInputStream = xStream->getInputStream(); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { + // ignore exception, if reason was problem reasoned on + // open it in WRITEABLE mode! Then we try it READONLY + // later a second time. + // All other errors must be handled as real error an + // break this method. + if (!pInteraction->wasWriteError() || bModeRequestedExplicitly) + return sal_False; + xStream.clear(); + xInputStream.clear(); + } + } + + // If opening of the stream in read/write mode wasnt allowed + // or failed by an error - we must try it in readonly mode. + if (!xInputStream.is()) + { + rtl::OUString aScheme; + + try + { + css::uno::Reference< css::ucb::XContentIdentifier > xContId( + aContent.get().is() ? aContent.get()->getIdentifier() : 0 ); + + if ( xContId.is() ) + aScheme = xContId->getContentProviderScheme(); + + // Only file system content provider is able to provide XStream + // so for this content impossibility to create XStream triggers + // switch to readonly mode in case of opening with locking on + if( bLockFile && aScheme.equalsIgnoreAsciiCaseAscii( "file" ) ) + bReadOnly = sal_True; + else + { + sal_Bool bRequestReadOnly = bReadOnly; + aContent.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bReadOnly; + if ( bReadOnly && !bRequestReadOnly && bModeRequestedExplicitly ) + return sal_False; // the document is explicitly requested with WRITEABLE mode + } + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { /* no error handling if IsReadOnly property does not exist for UCP */ } + + if ( bReadOnly ) + (*this)[MediaDescriptor::PROP_READONLY()] <<= bReadOnly; + + pInteraction->resetInterceptions(); + pInteraction->resetErrorStates(); + try + { + // all the contents except file-URLs should be opened as usual + if ( bLockFile || !aScheme.equalsIgnoreAsciiCaseAscii( "file" ) ) + xInputStream = aContent.openStream(); + else + xInputStream = aContent.openStreamNoLock(); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { return sal_False; } + } + + // add streams to the descriptor + if (xContent.is()) + (*this)[MediaDescriptor::PROP_UCBCONTENT()] <<= xContent; + if (xStream.is()) + (*this)[MediaDescriptor::PROP_STREAM()] <<= xStream; + if (xInputStream.is()) + (*this)[MediaDescriptor::PROP_INPUTSTREAM()] <<= xInputStream; + + // At least we need an input stream. The r/w stream is optional ... + return xInputStream.is(); +} + +/*----------------------------------------------- + 10.09.2004 10:51 +-----------------------------------------------*/ +::rtl::OUString MediaDescriptor::impl_normalizeURL(const ::rtl::OUString& sURL) +{ + /* Remove Jumpmarks (fragments) of an URL only here. + They are not part of any URL and as a result may be + no ucb content can be created then. + On the other side arguments must exists ... because + they are part of an URL. + + Do not use the URLTransformer service here. Because + it parses the URL in another way. It's main part isnt enough + and it's complete part contains the jumpmark (fragment) parameter ... + */ + static ::rtl::OUString SERVICENAME_URIREFERENCEFACTORY = ::rtl::OUString::createFromAscii("com.sun.star.uri.UriReferenceFactory"); + + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + css::uno::Reference< css::uri::XUriReferenceFactory > xUriFactory(xSMGR->createInstance(SERVICENAME_URIREFERENCEFACTORY), css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::uri::XUriReference > xUriRef = xUriFactory->parse(sURL); + if (xUriRef.is()) + { + xUriRef->clearFragment(); + return xUriRef->getUriReference(); + } + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} + + // If an error ocurred ... return the original URL. + // It's a try .-) + return sURL; +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/mimeconfighelper.cxx b/comphelper/source/misc/mimeconfighelper.cxx new file mode 100644 index 000000000000..2f3f5e445a74 --- /dev/null +++ b/comphelper/source/misc/mimeconfighelper.cxx @@ -0,0 +1,807 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/document/XTypeDetection.hpp> + +#include <comphelper/fileformat.h> +#include <comphelper/mimeconfighelper.hxx> +#include <comphelper/classids.hxx> +#include <comphelper/sequenceashashmap.hxx> + + +using namespace ::com::sun::star; +using namespace comphelper; + +//----------------------------------------------------------------------- +MimeConfigurationHelper::MimeConfigurationHelper( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +: m_xFactory( xFactory ) +{ + if ( !m_xFactory.is() ) + throw uno::RuntimeException(); +} + +//----------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetStringClassIDRepresentation( const uno::Sequence< sal_Int8 >& aClassID ) +{ + ::rtl::OUString aResult; + + if ( aClassID.getLength() == 16 ) + { + for ( sal_Int32 nInd = 0; nInd < aClassID.getLength(); nInd++ ) + { + if ( nInd == 4 || nInd == 6 || nInd == 8 || nInd == 10 ) + aResult += ::rtl::OUString::createFromAscii( "-" ); + + sal_Int32 nDigit1 = (sal_Int32)( (sal_uInt8)aClassID[nInd] / 16 ); + sal_Int32 nDigit2 = (sal_uInt8)aClassID[nInd] % 16; + aResult += ::rtl::OUString::valueOf( nDigit1, 16 ); + aResult += ::rtl::OUString::valueOf( nDigit2, 16 ); + } + } + + return aResult; +} + +//----------------------------------------------------------------------- +sal_uInt8 GetDigit_Impl( sal_Char aChar ) +{ + if ( aChar >= '0' && aChar <= '9' ) + return aChar - '0'; + else if ( aChar >= 'a' && aChar <= 'f' ) + return aChar - 'a' + 10; + else if ( aChar >= 'A' && aChar <= 'F' ) + return aChar - 'A' + 10; + else + return 16; +} + +//----------------------------------------------------------------------- +uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( const ::rtl::OUString& aClassID ) +{ + sal_Int32 nLength = aClassID.getLength(); + if ( nLength == 36 ) + { + ::rtl::OString aCharClassID = ::rtl::OUStringToOString( aClassID, RTL_TEXTENCODING_ASCII_US ); + const sal_Char* pString = aCharClassID.getStr(); + if ( pString ) + { + uno::Sequence< sal_Int8 > aResult( 16 ); + + sal_Int32 nStrPointer = 0; + sal_Int32 nSeqInd = 0; + while( nSeqInd < 16 && nStrPointer + 1 < nLength ) + { + sal_uInt8 nDigit1 = GetDigit_Impl( pString[nStrPointer++] ); + sal_uInt8 nDigit2 = GetDigit_Impl( pString[nStrPointer++] ); + + if ( nDigit1 > 15 || nDigit2 > 15 ) + break; + + aResult[nSeqInd++] = (sal_Int8)( nDigit1 * 16 + nDigit2 ); + + if ( nStrPointer < nLength && pString[nStrPointer] == '-' ) + nStrPointer++; + } + + if ( nSeqInd == 16 && nStrPointer == nLength ) + return aResult; + } + } + + return uno::Sequence< sal_Int8 >(); +} + +//----------------------------------------------------------------------- +uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPath( const ::rtl::OUString& aPath ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< container::XNameAccess > xConfig; + + try + { + if ( !m_xConfigProvider.is() ) + m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( + m_xFactory->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ) ), + uno::UNO_QUERY_THROW ); + + uno::Sequence< uno::Any > aArgs( 1 ); + beans::PropertyValue aPathProp; + aPathProp.Name = ::rtl::OUString::createFromAscii( "nodepath" ); + aPathProp.Value <<= aPath; + aArgs[0] <<= aPathProp; + + xConfig = uno::Reference< container::XNameAccess >( + m_xConfigProvider->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ), + aArgs ), + uno::UNO_QUERY ); + } + catch( uno::Exception& ) + {} + + return xConfig; +} + +//----------------------------------------------------------------------- +uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfiguration() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xObjectConfig.is() ) + m_xObjectConfig = GetConfigurationByPath( + ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Embedding/Objects" ) ); + + return m_xObjectConfig; +} + +//----------------------------------------------------------------------- +uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfiguration() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xVerbsConfig.is() ) + m_xVerbsConfig = GetConfigurationByPath( + ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Embedding/Verbs" ) ); + + return m_xVerbsConfig; +} + +//----------------------------------------------------------------------- +uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeConfiguration() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xMediaTypeConfig.is() ) + m_xMediaTypeConfig = GetConfigurationByPath( + ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations" ) ); + + return m_xMediaTypeConfig; +} +//------------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetDocServiceNameFromFilter( const ::rtl::OUString& aFilterName ) +{ + ::rtl::OUString aDocServiceName; + + try + { + uno::Reference< container::XNameAccess > xFilterFactory( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), + uno::UNO_QUERY_THROW ); + + uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName ); + uno::Sequence< beans::PropertyValue > aFilterData; + if ( aFilterAnyData >>= aFilterData ) + { + for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ ) + if ( aFilterData[nInd].Name.equalsAscii( "DocumentService" ) ) + aFilterData[nInd].Value >>= aDocServiceName; + } + } + catch( uno::Exception& ) + {} + + return aDocServiceName; +} + +//------------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const ::rtl::OUString& aMediaType ) +{ + uno::Reference< container::XContainerQuery > xTypeCFG( + m_xFactory->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ), + uno::UNO_QUERY ); + + if ( xTypeCFG.is() ) + { + try + { + // make query for all types matching the properties + uno::Sequence < beans::NamedValue > aSeq( 1 ); + aSeq[0].Name = ::rtl::OUString::createFromAscii( "MediaType" ); + aSeq[0].Value <<= aMediaType; + + uno::Reference < container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq ); + while ( xEnum->hasMoreElements() ) + { + uno::Sequence< beans::PropertyValue > aType; + if ( xEnum->nextElement() >>= aType ) + { + for ( sal_Int32 nInd = 0; nInd < aType.getLength(); nInd++ ) + { + ::rtl::OUString aFilterName; + if ( aType[nInd].Name.equalsAscii( "PreferredFilter" ) + && ( aType[nInd].Value >>= aFilterName ) && aFilterName.getLength() ) + { + ::rtl::OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName ); + if ( aDocumentName.getLength() ) + return aDocumentName; + } + } + } + } + } + catch( uno::Exception& ) + {} + } + + return ::rtl::OUString(); +} + +//------------------------------------------------------------------------- +sal_Bool MimeConfigurationHelper::GetVerbByShortcut( const ::rtl::OUString& aVerbShortcut, + embed::VerbDescriptor& aDescriptor ) +{ + sal_Bool bResult = sal_False; + + uno::Reference< container::XNameAccess > xVerbsConfig = GetVerbsConfiguration(); + uno::Reference< container::XNameAccess > xVerbsProps; + try + { + if ( xVerbsConfig.is() && ( xVerbsConfig->getByName( aVerbShortcut ) >>= xVerbsProps ) && xVerbsProps.is() ) + { + embed::VerbDescriptor aTempDescr; + if ( ( xVerbsProps->getByName( ::rtl::OUString::createFromAscii( "VerbID" ) ) >>= aTempDescr.VerbID ) + && ( xVerbsProps->getByName( ::rtl::OUString::createFromAscii( "VerbUIName" ) ) >>= aTempDescr.VerbName ) + && ( xVerbsProps->getByName( ::rtl::OUString::createFromAscii( "VerbFlags" ) ) >>= aTempDescr.VerbFlags ) + && ( xVerbsProps->getByName( ::rtl::OUString::createFromAscii( "VerbAttributes" ) ) >>= aTempDescr.VerbAttributes ) ) + { + aDescriptor = aTempDescr; + bResult = sal_True; + } + } + } + catch( uno::Exception& ) + { + } + + return bResult; +} + +//------------------------------------------------------------------------- +uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjPropsFromConfigEntry( + const uno::Sequence< sal_Int8 >& aClassID, + const uno::Reference< container::XNameAccess >& xObjectProps ) +{ + uno::Sequence< beans::NamedValue > aResult; + + if ( aClassID.getLength() == 16 ) + { + try + { + uno::Sequence< ::rtl::OUString > aObjPropNames = xObjectProps->getElementNames(); + + aResult.realloc( aObjPropNames.getLength() + 1 ); + aResult[0].Name = ::rtl::OUString::createFromAscii( "ClassID" ); + aResult[0].Value <<= aClassID; + + for ( sal_Int32 nInd = 0; nInd < aObjPropNames.getLength(); nInd++ ) + { + aResult[nInd + 1].Name = aObjPropNames[nInd]; + + if ( aObjPropNames[nInd].equalsAscii( "ObjectVerbs" ) ) + { + uno::Sequence< ::rtl::OUString > aVerbShortcuts; + if ( xObjectProps->getByName( aObjPropNames[nInd] ) >>= aVerbShortcuts ) + { + uno::Sequence< embed::VerbDescriptor > aVerbDescriptors( aVerbShortcuts.getLength() ); + for ( sal_Int32 nVerbI = 0; nVerbI < aVerbShortcuts.getLength(); nVerbI++ ) + if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptors[nVerbI] ) ) + throw uno::RuntimeException(); + + aResult[nInd+1].Value <<= aVerbDescriptors; + } + else + throw uno::RuntimeException(); + } + else + aResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] ); + } + } + catch( uno::Exception& ) + { + aResult.realloc( 0 ); + } + } + + return aResult; +} + +//----------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetExplicitlyRegisteredObjClassID( const ::rtl::OUString& aMediaType ) +{ + ::rtl::OUString aStringClassID; + + uno::Reference< container::XNameAccess > xMediaTypeConfig = GetMediaTypeConfiguration(); + try + { + if ( xMediaTypeConfig.is() ) + xMediaTypeConfig->getByName( aMediaType ) >>= aStringClassID; + } + catch( uno::Exception& ) + { + } + + return aStringClassID; + +} + +//----------------------------------------------------------------------- +uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByStringClassID( + const ::rtl::OUString& aStringClassID ) +{ + uno::Sequence< beans::NamedValue > aObjProps; + + uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID ); + if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) + { + aObjProps.realloc(2); + aObjProps[0].Name = ::rtl::OUString::createFromAscii("ObjectFactory"); + aObjProps[0].Value <<= ::rtl::OUString::createFromAscii("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"); + aObjProps[1].Name = ::rtl::OUString::createFromAscii("ClassID"); + aObjProps[1].Value <<= aClassID; + return aObjProps; + } + + if ( aClassID.getLength() == 16 ) + { + uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration(); + uno::Reference< container::XNameAccess > xObjectProps; + try + { + // TODO/LATER: allow to provide ClassID string in any format, only digits are counted + if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() ) + aObjProps = GetObjPropsFromConfigEntry( aClassID, xObjectProps ); + } + catch( uno::Exception& ) + { + } + } + + return aObjProps; +} + +//----------------------------------------------------------------------- +uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByClassID( + const uno::Sequence< sal_Int8 >& aClassID ) +{ + uno::Sequence< beans::NamedValue > aObjProps; + if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) + { + aObjProps.realloc(2); + aObjProps[0].Name = ::rtl::OUString::createFromAscii("ObjectFactory"); + aObjProps[0].Value <<= ::rtl::OUString::createFromAscii("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"); + aObjProps[1].Name = ::rtl::OUString::createFromAscii("ClassID"); + aObjProps[1].Value <<= aClassID; + } + + ::rtl::OUString aStringClassID = GetStringClassIDRepresentation( aClassID ); + if ( aStringClassID.getLength() ) + { + uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration(); + uno::Reference< container::XNameAccess > xObjectProps; + try + { + if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() ) + aObjProps = GetObjPropsFromConfigEntry( aClassID, xObjectProps ); + } + catch( uno::Exception& ) + { + } + } + + return aObjProps; +} + +//----------------------------------------------------------------------- +uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByMediaType( const ::rtl::OUString& aMediaType ) +{ + uno::Sequence< beans::NamedValue > aObject = + GetObjectPropsByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) ); + if ( aObject.getLength() ) + return aObject; + + ::rtl::OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType ); + if ( aDocumentName.getLength() ) + return GetObjectPropsByDocumentName( aDocumentName ); + + return uno::Sequence< beans::NamedValue >(); +} + +//----------------------------------------------------------------------- +uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByFilter( const ::rtl::OUString& aFilterName ) +{ + ::rtl::OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName ); + if ( aDocumentName.getLength() ) + return GetObjectPropsByDocumentName( aDocumentName ); + + return uno::Sequence< beans::NamedValue >(); +} + +//----------------------------------------------------------------------- +uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocumentName( const ::rtl::OUString& aDocName ) +{ + if ( aDocName.getLength() ) + { + uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration(); + if ( xObjConfig.is() ) + { + try + { + uno::Sequence< ::rtl::OUString > aClassIDs = xObjConfig->getElementNames(); + for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ ) + { + uno::Reference< container::XNameAccess > xObjectProps; + ::rtl::OUString aEntryDocName; + + if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is() + && ( xObjectProps->getByName( + ::rtl::OUString::createFromAscii( "ObjectDocumentServiceName" ) ) >>= aEntryDocName ) + && aEntryDocName.equals( aDocName ) ) + { + return GetObjPropsFromConfigEntry( GetSequenceClassIDRepresentation( aClassIDs[nInd] ), + xObjectProps ); + } + } + } + catch( uno::Exception& ) + {} + } + } + + return uno::Sequence< beans::NamedValue >(); +} + +//----------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetFactoryNameByClassID( const uno::Sequence< sal_Int8 >& aClassID ) +{ + return GetFactoryNameByStringClassID( GetStringClassIDRepresentation( aClassID ) ); +} + +//----------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetFactoryNameByStringClassID( const ::rtl::OUString& aStringClassID ) +{ + ::rtl::OUString aResult; + + if ( aStringClassID.getLength() ) + { + uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration(); + uno::Reference< container::XNameAccess > xObjectProps; + try + { + if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() ) + xObjectProps->getByName( ::rtl::OUString::createFromAscii( "ObjectFactory" ) ) >>= aResult; + } + catch( uno::Exception& ) + { + uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID ); + if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) + return ::rtl::OUString::createFromAscii("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"); + } + } + + return aResult; +} + +//----------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( const ::rtl::OUString& aDocName ) +{ + ::rtl::OUString aResult; + + if ( aDocName.getLength() ) + { + uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration(); + if ( xObjConfig.is() ) + { + try + { + uno::Sequence< ::rtl::OUString > aClassIDs = xObjConfig->getElementNames(); + for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ ) + { + uno::Reference< container::XNameAccess > xObjectProps; + ::rtl::OUString aEntryDocName; + + if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is() + && ( xObjectProps->getByName( + ::rtl::OUString::createFromAscii( "ObjectDocumentServiceName" ) ) >>= aEntryDocName ) + && aEntryDocName.equals( aDocName ) ) + { + xObjectProps->getByName( ::rtl::OUString::createFromAscii( "ObjectFactory" ) ) >>= aResult; + break; + } + } + } + catch( uno::Exception& ) + {} + } + } + + return aResult; +} + + +//----------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetFactoryNameByMediaType( const ::rtl::OUString& aMediaType ) +{ + ::rtl::OUString aResult = GetFactoryNameByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) ); + + if ( !aResult.getLength() ) + { + ::rtl::OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType ); + if ( aDocumentName.getLength() ) + aResult = GetFactoryNameByDocumentName( aDocumentName ); + } + + return aResult; +} + +//----------------------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( + uno::Sequence< beans::PropertyValue >& aMediaDescr, + sal_Bool bIgnoreType ) +{ + ::rtl::OUString aFilterName; + + for ( sal_Int32 nInd = 0; nInd < aMediaDescr.getLength(); nInd++ ) + if ( aMediaDescr[nInd].Name.equalsAscii( "FilterName" ) ) + aMediaDescr[nInd].Value >>= aFilterName; + + if ( !aFilterName.getLength() ) + { + // filter name is not specified, so type detection should be done + + uno::Reference< document::XTypeDetection > xTypeDetection( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ), + uno::UNO_QUERY ); + + if ( !xTypeDetection.is() ) + throw uno::RuntimeException(); // TODO + + // typedetection can change the mode, add a stream and so on, thus a copy should be used + uno::Sequence< beans::PropertyValue > aTempMD( aMediaDescr ); + + // get TypeName + ::rtl::OUString aTypeName = xTypeDetection->queryTypeByDescriptor( aTempMD, sal_True ); + + // get FilterName + for ( sal_Int32 nInd = 0; nInd < aTempMD.getLength(); nInd++ ) + if ( aTempMD[nInd].Name.equalsAscii( "FilterName" ) ) + aTempMD[nInd].Value >>= aFilterName; + + if ( aFilterName.getLength() ) + { + sal_Int32 nOldLen = aMediaDescr.getLength(); + aMediaDescr.realloc( nOldLen + 1 ); + aMediaDescr[nOldLen].Name = ::rtl::OUString::createFromAscii( "FilterName" ); + aMediaDescr[ nOldLen ].Value <<= aFilterName; + + } + else if ( aTypeName.getLength() && !bIgnoreType ) + { + uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY ); + uno::Sequence< beans::PropertyValue > aTypes; + + if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) ) + { + for ( sal_Int32 nInd = 0; nInd < aTypes.getLength(); nInd++ ) + { + if ( aTypes[nInd].Name.equalsAscii( "PreferredFilter" ) && ( aTypes[nInd].Value >>= aFilterName ) ) + { + sal_Int32 nOldLen = aMediaDescr.getLength(); + aMediaDescr.realloc( nOldLen + 1 ); + aMediaDescr[nOldLen].Name = ::rtl::OUString::createFromAscii( "FilterName" ); + aMediaDescr[ nOldLen ].Value = aTypes[nInd].Value; + break; + } + } + } + } + } + + return aFilterName; +} + +::rtl::OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( + uno::Sequence< beans::PropertyValue >& aMediaDescr, + uno::Sequence< beans::NamedValue >& aObject ) +{ + ::rtl::OUString aDocName; + for ( sal_Int32 nInd = 0; nInd < aObject.getLength(); nInd++ ) + if ( aObject[nInd].Name.equalsAscii( "ObjectDocumentServiceName" ) ) + { + aObject[nInd].Value >>= aDocName; + break; + } + + OSL_ENSURE( aDocName.getLength(), "The name must exist at this point!\n" ); + + + sal_Bool bNeedsAddition = sal_True; + for ( sal_Int32 nMedInd = 0; nMedInd < aMediaDescr.getLength(); nMedInd++ ) + if ( aMediaDescr[nMedInd].Name.equalsAscii( "DocumentService" ) ) + { + aMediaDescr[nMedInd].Value <<= aDocName; + bNeedsAddition = sal_False; + break; + } + + if ( bNeedsAddition ) + { + sal_Int32 nOldLen = aMediaDescr.getLength(); + aMediaDescr.realloc( nOldLen + 1 ); + aMediaDescr[nOldLen].Name = ::rtl::OUString::createFromAscii( "DocumentService" ); + aMediaDescr[nOldLen].Value <<= aDocName; + } + + return UpdateMediaDescriptorWithFilterName( aMediaDescr, sal_True ); +} + +sal_Bool MimeConfigurationHelper::AddFilterNameCheckOwnFile( + uno::Sequence< beans::PropertyValue >& aMediaDescr ) +{ + ::rtl::OUString aFilterName = UpdateMediaDescriptorWithFilterName( aMediaDescr, sal_False ); + if ( aFilterName.getLength() ) + { + try + { + uno::Reference< container::XNameAccess > xFilterFactory( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), + uno::UNO_QUERY_THROW ); + + uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName ); + uno::Sequence< beans::PropertyValue > aFilterData; + if ( aFilterAnyData >>= aFilterData ) + { + for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ ) + if ( aFilterData[nInd].Name.equalsAscii( "Flags" ) ) + { + uno::Any aVal = aFilterData[nInd].Value; + sal_Int32 nFlags = 0; + // check the OWN flag + if ( ( aFilterData[nInd].Value >>= nFlags ) && ( nFlags & 0x20 ) ) + return sal_True; + break; + } + } + } + catch( uno::Exception& ) + {} + } + + return sal_False; +} + +//----------------------------------------------------------- +::rtl::OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const ::rtl::OUString& aServiceName, sal_Int32 nVersion ) +{ + rtl::OUString aResult; + + if ( aServiceName.getLength() && nVersion ) + try + { + uno::Reference< container::XContainerQuery > xFilterQuery( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), + uno::UNO_QUERY_THROW ); + + uno::Sequence< beans::NamedValue > aSearchRequest( 2 ); + aSearchRequest[0].Name = ::rtl::OUString::createFromAscii( "DocumentService" ); + aSearchRequest[0].Value <<= aServiceName; + aSearchRequest[1].Name = ::rtl::OUString::createFromAscii( "FileFormatVersion" ); + aSearchRequest[1].Value <<= nVersion; + + uno::Sequence< beans::PropertyValue > aFilterProps; + uno::Reference< container::XEnumeration > xFilterEnum = + xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest ); + + // use the first filter that is found + if ( xFilterEnum.is() ) + while ( xFilterEnum->hasMoreElements() ) + { + uno::Sequence< beans::PropertyValue > aProps; + if ( xFilterEnum->nextElement() >>= aProps ) + { + SequenceAsHashMap aPropsHM( aProps ); + sal_Int32 nFlags = aPropsHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Flags" ), + (sal_Int32)0 ); + + // that should be import, export, own filter and not a template filter ( TemplatePath flag ) + if ( ( ( nFlags & 0x23L ) == 0x23L ) && !( nFlags & 0x10 ) ) + { + // if there are more than one filter the preffered one should be used + // if there is no preffered filter the first one will be used + if ( !aResult.getLength() || ( nFlags & 0x10000000L ) ) + aResult = aPropsHM.getUnpackedValueOrDefault( ::rtl::OUString::createFromAscii( "Name" ), + ::rtl::OUString() ); + if ( nFlags & 0x10000000L ) + break; // the preffered filter was found + } + } + } + } + catch( uno::Exception& ) + {} + + return aResult; +} +//------------------------------------------------------------------------- +sal_Bool MimeConfigurationHelper::ClassIDsEqual( const uno::Sequence< sal_Int8 >& aClassID1, const uno::Sequence< sal_Int8 >& aClassID2 ) +{ + if ( aClassID1.getLength() != aClassID2.getLength() ) + return sal_False; + + for ( sal_Int32 nInd = 0; nInd < aClassID1.getLength(); nInd++ ) + if ( aClassID1[nInd] != aClassID2[nInd] ) + return sal_False; + + return sal_True; +} +//---------------------------------------------- +uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassID( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3, + sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, + sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 ) +{ + uno::Sequence< sal_Int8 > aResult( 16 ); + aResult[0] = (sal_Int8)( n1 >> 24 ); + aResult[1] = (sal_Int8)( ( n1 << 8 ) >> 24 ); + aResult[2] = (sal_Int8)( ( n1 << 16 ) >> 24 ); + aResult[3] = (sal_Int8)( ( n1 << 24 ) >> 24 ); + aResult[4] = (sal_Int8)( n2 >> 8 ); + aResult[5] = (sal_Int8)( ( n2 << 8 ) >> 8 ); + aResult[6] = (sal_Int8)( n3 >> 8 ); + aResult[7] = (sal_Int8)( ( n3 << 8 ) >> 8 ); + aResult[8] = b8; + aResult[9] = b9; + aResult[10] = b10; + aResult[11] = b11; + aResult[12] = b12; + aResult[13] = b13; + aResult[14] = b14; + aResult[15] = b15; + + return aResult; +} +uno::Sequence<sal_Int8> MimeConfigurationHelper::GetSequenceClassIDFromObjectName(const ::rtl::OUString& _sObjectName) +{ + uno::Sequence<sal_Int8> aClassId; + uno::Reference< container::XNameAccess > xObjectNames = GetConfigurationByPath(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Embedding/ObjectNames"))); + uno::Reference< container::XNameAccess > xProps; + if ( xObjectNames.is() && (xObjectNames->getByName(_sObjectName) >>= xProps) && xProps.is() ) + { + ::rtl::OUString sValue; + xProps->getByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ClassID"))) >>= sValue; + aClassId = GetSequenceClassIDRepresentation(sValue); + } + return aClassId; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/namedvaluecollection.cxx b/comphelper/source/misc/namedvaluecollection.cxx new file mode 100644 index 000000000000..2031a338cb4e --- /dev/null +++ b/comphelper/source/misc/namedvaluecollection.cxx @@ -0,0 +1,340 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/namedvaluecollection.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +/** === end UNO includes === **/ + +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <osl/diagnose.h> + +#include <hash_map> +#include <functional> +#include <algorithm> + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::beans::NamedValue; + using ::com::sun::star::uno::Type; + using ::com::sun::star::uno::cpp_acquire; + using ::com::sun::star::uno::cpp_release; + using ::com::sun::star::uno::cpp_queryInterface; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::beans::NamedValue; + using ::com::sun::star::beans::PropertyState_DIRECT_VALUE; + /** === end UNO using === **/ + + //==================================================================== + //= NamedValueCollection_Impl + //==================================================================== + typedef ::std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash > NamedValueRepository; + + struct NamedValueCollection_Impl + { + NamedValueRepository aValues; + }; + + //==================================================================== + //= NamedValueCollection + //==================================================================== + //-------------------------------------------------------------------- + NamedValueCollection::NamedValueCollection() + :m_pImpl( new NamedValueCollection_Impl ) + { + } + + //-------------------------------------------------------------------- + NamedValueCollection::NamedValueCollection( const NamedValueCollection& _rCopySource ) + :m_pImpl( new NamedValueCollection_Impl ) + { + *this = _rCopySource; + } + + //-------------------------------------------------------------------- + NamedValueCollection& NamedValueCollection::operator=( const NamedValueCollection& i_rCopySource ) + { + m_pImpl->aValues = i_rCopySource.m_pImpl->aValues; + return *this; + } + + //-------------------------------------------------------------------- + NamedValueCollection::NamedValueCollection( const Any& _rElements ) + :m_pImpl( new NamedValueCollection_Impl ) + { + Sequence< NamedValue > aNamedValues; + Sequence< PropertyValue > aPropertyValues; + NamedValue aNamedValue; + PropertyValue aPropertyValue; + + if ( _rElements >>= aNamedValues ) + impl_assign( aNamedValues ); + else if ( _rElements >>= aPropertyValues ) + impl_assign( aPropertyValues ); + else if ( _rElements >>= aNamedValue ) + impl_assign( Sequence< NamedValue >( &aNamedValue, 1 ) ); + else if ( _rElements >>= aPropertyValue ) + impl_assign( Sequence< PropertyValue >( &aPropertyValue, 1 ) ); + else + OSL_ENSURE( !_rElements.hasValue(), "NamedValueCollection::NamedValueCollection(Any): unsupported type!" ); + } + + //-------------------------------------------------------------------- + NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments ) + :m_pImpl( new NamedValueCollection_Impl ) + { + impl_assign( _rArguments ); + } + + //-------------------------------------------------------------------- + NamedValueCollection::NamedValueCollection( const Sequence< PropertyValue >& _rArguments ) + :m_pImpl( new NamedValueCollection_Impl ) + { + impl_assign( _rArguments ); + } + + //-------------------------------------------------------------------- + NamedValueCollection::NamedValueCollection( const Sequence< NamedValue >& _rArguments ) + :m_pImpl( new NamedValueCollection_Impl ) + { + impl_assign( _rArguments ); + } + + //-------------------------------------------------------------------- + NamedValueCollection::~NamedValueCollection() + { + } + + //-------------------------------------------------------------------- + NamedValueCollection& NamedValueCollection::merge( const NamedValueCollection& _rAdditionalValues, bool _bOverwriteExisting ) + { + for ( NamedValueRepository::const_iterator namedValue = _rAdditionalValues.m_pImpl->aValues.begin(); + namedValue != _rAdditionalValues.m_pImpl->aValues.end(); + ++namedValue + ) + { + if ( _bOverwriteExisting || !impl_has( namedValue->first ) ) + impl_put( namedValue->first, namedValue->second ); + } + + return *this; + } + + //-------------------------------------------------------------------- + size_t NamedValueCollection::size() const + { + return m_pImpl->aValues.size(); + } + + //-------------------------------------------------------------------- + bool NamedValueCollection::empty() const + { + return m_pImpl->aValues.empty(); + } + + //-------------------------------------------------------------------- + void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments ) + { + { + NamedValueRepository aEmpty; + m_pImpl->aValues.swap( aEmpty ); + } + + PropertyValue aPropertyValue; + NamedValue aNamedValue; + + const Any* pArgument = _rArguments.getConstArray(); + const Any* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); + for ( ; pArgument != pArgumentEnd; ++pArgument ) + { + if ( *pArgument >>= aPropertyValue ) + m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value; + else if ( *pArgument >>= aNamedValue ) + m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value; +#if OSL_DEBUG_LEVEL > 0 + else if ( pArgument->hasValue() ) + { + ::rtl::OStringBuffer message; + message.append( "NamedValueCollection::impl_assign: encountered a value type which I cannot handle:\n" ); + message.append( ::rtl::OUStringToOString( pArgument->getValueTypeName(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_ENSURE( false, message.makeStringAndClear() ); + } +#endif + } + } + + //-------------------------------------------------------------------- + void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments ) + { + { + NamedValueRepository aEmpty; + m_pImpl->aValues.swap( aEmpty ); + } + + const PropertyValue* pArgument = _rArguments.getConstArray(); + const PropertyValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); + for ( ; pArgument != pArgumentEnd; ++pArgument ) + m_pImpl->aValues[ pArgument->Name ] = pArgument->Value; + } + + //-------------------------------------------------------------------- + void NamedValueCollection::impl_assign( const Sequence< NamedValue >& _rArguments ) + { + { + NamedValueRepository aEmpty; + m_pImpl->aValues.swap( aEmpty ); + } + + const NamedValue* pArgument = _rArguments.getConstArray(); + const NamedValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); + for ( ; pArgument != pArgumentEnd; ++pArgument ) + m_pImpl->aValues[ pArgument->Name ] = pArgument->Value; + } + + //-------------------------------------------------------------------- + bool NamedValueCollection::get_ensureType( const ::rtl::OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const + { + NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); + if ( pos != m_pImpl->aValues.end() ) + { + if ( uno_type_assignData( + _pValueLocation, _rExpectedValueType.getTypeLibType(), + const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(), + reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), + reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), + reinterpret_cast< uno_ReleaseFunc >( cpp_release ) + ) ) + // argument exists, and could be extracted + return true; + + // argument exists, but is of wrong type + ::rtl::OUStringBuffer aBuffer; + aBuffer.appendAscii( "Invalid value type for '" ); + aBuffer.append ( _rValueName ); + aBuffer.appendAscii( "'.\nExpected: " ); + aBuffer.append ( _rExpectedValueType.getTypeName() ); + aBuffer.appendAscii( "\nFound: " ); + aBuffer.append ( pos->second.getValueType().getTypeName() ); + throw IllegalArgumentException( aBuffer.makeStringAndClear(), NULL, 0 ); + } + + // argument does not exist + return false; + } + + //-------------------------------------------------------------------- + const Any& NamedValueCollection::impl_get( const ::rtl::OUString& _rValueName ) const + { + NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); + if ( pos != m_pImpl->aValues.end() ) + return pos->second; + + static Any aEmptyDefault; + return aEmptyDefault; + } + + //-------------------------------------------------------------------- + bool NamedValueCollection::impl_has( const ::rtl::OUString& _rValueName ) const + { + NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); + return ( pos != m_pImpl->aValues.end() ); + } + + //-------------------------------------------------------------------- + bool NamedValueCollection::impl_put( const ::rtl::OUString& _rValueName, const Any& _rValue ) + { + bool bHas = impl_has( _rValueName ); + m_pImpl->aValues[ _rValueName ] = _rValue; + return bHas; + } + + //-------------------------------------------------------------------- + bool NamedValueCollection::impl_remove( const ::rtl::OUString& _rValueName ) + { + NamedValueRepository::iterator pos = m_pImpl->aValues.find( _rValueName ); + if ( pos == m_pImpl->aValues.end() ) + return false; + m_pImpl->aValues.erase( pos ); + return true; + } + + //-------------------------------------------------------------------- + namespace + { + struct Value2PropertyValue : public ::std::unary_function< NamedValueRepository::value_type, PropertyValue > + { + PropertyValue operator()( const NamedValueRepository::value_type& _rValue ) + { + return PropertyValue( + _rValue.first, 0, _rValue.second, PropertyState_DIRECT_VALUE ); + } + }; + + struct Value2NamedValue : public ::std::unary_function< NamedValueRepository::value_type, NamedValue > + { + NamedValue operator()( const NamedValueRepository::value_type& _rValue ) + { + return NamedValue( _rValue.first, _rValue.second ); + } + }; + } + + //-------------------------------------------------------------------- + sal_Int32 NamedValueCollection::operator >>= ( Sequence< PropertyValue >& _out_rValues ) const + { + _out_rValues.realloc( m_pImpl->aValues.size() ); + ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2PropertyValue() ); + return _out_rValues.getLength(); + } + + //-------------------------------------------------------------------- + sal_Int32 NamedValueCollection::operator >>= ( Sequence< NamedValue >& _out_rValues ) const + { + _out_rValues.realloc( m_pImpl->aValues.size() ); + ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2NamedValue() ); + return _out_rValues.getLength(); + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/numberedcollection.cxx b/comphelper/source/misc/numberedcollection.cxx new file mode 100644 index 000000000000..e8374efc2e4d --- /dev/null +++ b/comphelper/source/misc/numberedcollection.cxx @@ -0,0 +1,278 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include <comphelper/numberedcollection.hxx> + +//_______________________________________________ +// includes + +#include <com/sun/star/frame/UntitledNumbersConst.hpp> + +//_______________________________________________ +// namespace + +namespace comphelper{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +static const ::rtl::OUString ERRMSG_INVALID_COMPONENT_PARAM(RTL_CONSTASCII_USTRINGPARAM("NULL as component reference not allowed.")); + +//----------------------------------------------- +NumberedCollection::NumberedCollection() + : ::cppu::BaseMutex () + , m_sUntitledPrefix () + , m_lComponents () + , m_xOwner () +{ +} + +//----------------------------------------------- +NumberedCollection::~NumberedCollection() +{ +} + +//----------------------------------------------- +void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_xOwner = xOwner; + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +void NumberedCollection::setUntitledPrefix(const ::rtl::OUString& sPrefix) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + m_sUntitledPrefix = sPrefix; + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +::sal_Int32 SAL_CALL NumberedCollection::leaseNumber(const css::uno::Reference< css::uno::XInterface >& xComponent) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + if ( ! xComponent.is ()) + throw css::lang::IllegalArgumentException (ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); + + long pComponent = (long) xComponent.get (); + TNumberedItemHash::const_iterator pIt = m_lComponents.find (pComponent); + + // a) component already exists - return it's number directly + if (pIt != m_lComponents.end()) + return pIt->second.nNumber; + + // b) component must be added new to this container + + // b1) collection is full - no further components possible + // -> return INVALID_NUMBER + ::sal_Int32 nFreeNumber = impl_searchFreeNumber(); + if (nFreeNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) + return css::frame::UntitledNumbersConst::INVALID_NUMBER; + + // b2) add component to collection and return its number + TNumberedItem aItem; + aItem.xItem = css::uno::WeakReference< css::uno::XInterface >(xComponent); + aItem.nNumber = nFreeNumber; + m_lComponents[pComponent] = aItem; + + return nFreeNumber; + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + if (nNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) + throw css::lang::IllegalArgumentException (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Special valkud INVALID_NUMBER not allowed as input parameter.")), m_xOwner.get(), 1); + + TDeadItemList lDeadItems; + TNumberedItemHash::iterator pComponent; + + for ( pComponent = m_lComponents.begin (); + pComponent != m_lComponents.end (); + ++pComponent ) + { + const TNumberedItem& rItem = pComponent->second; + const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get(); + + if ( ! xItem.is ()) + { + lDeadItems.push_back(pComponent->first); + continue; + } + + if (rItem.nNumber == nNumber) + { + m_lComponents.erase (pComponent); + break; + } + } + + impl_cleanUpDeadItems(m_lComponents, lDeadItems); + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface >& xComponent) + throw (css::lang::IllegalArgumentException, + css::uno::RuntimeException ) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + if ( ! xComponent.is ()) + throw css::lang::IllegalArgumentException (ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); + + long pComponent = (long) xComponent.get (); + TNumberedItemHash::iterator pIt = m_lComponents.find (pComponent); + + // a) component exists and will be removed + if (pIt != m_lComponents.end()) + m_lComponents.erase(pIt); + + // else + // b) component does not exists - nothing todo here (ignore request!) + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +::rtl::OUString SAL_CALL NumberedCollection::getUntitledPrefix() + throw (css::uno::RuntimeException) +{ + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + return m_sUntitledPrefix; + + // <- SYNCHRONIZED +} + +//----------------------------------------------- +/** create an ordered list of all possible numbers ... + e.g. {1,2,3,...,N} Max size of these list will be + current size of component list + 1 . + + "+1" ... because in case all numbers in range 1..n + are in use we need a new number n+1 :-) + + Every item which is already used as unique number + will be removed. At the end a list of e.g. {3,6,...,M} + exists where the first item represent the lowest free + number (in this example 3). + */ +::sal_Int32 NumberedCollection::impl_searchFreeNumber () +{ + // create ordered list of all possible numbers. + ::std::vector< ::sal_Int32 > lPossibleNumbers; + ::sal_Int32 c = (::sal_Int32)m_lComponents.size (); + ::sal_Int32 i = 1; + + // c cant be less then 0 ... otherwhise hash.size() has an error :-) + // But we need at least n+1 numbers here. + c += 1; + + for (i=1; i<=c; ++i) + lPossibleNumbers.push_back (i); + + // SYNCHRONIZED -> + ::osl::ResettableMutexGuard aLock(m_aMutex); + + TDeadItemList lDeadItems; + TNumberedItemHash::const_iterator pComponent; + + for ( pComponent = m_lComponents.begin (); + pComponent != m_lComponents.end (); + ++pComponent ) + { + const TNumberedItem& rItem = pComponent->second; + const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get(); + + if ( ! xItem.is ()) + { + lDeadItems.push_back(pComponent->first); + continue; + } + + ::std::vector< ::sal_Int32 >::iterator pPossible = ::std::find(lPossibleNumbers.begin (), lPossibleNumbers.end (), rItem.nNumber); + if (pPossible != lPossibleNumbers.end ()) + lPossibleNumbers.erase (pPossible); + } + + impl_cleanUpDeadItems(m_lComponents, lDeadItems); + + // a) non free numbers ... return INVALID_NUMBER + if (lPossibleNumbers.size () < 1) + return css::frame::UntitledNumbersConst::INVALID_NUMBER; + + // b) return first free number + return *(lPossibleNumbers.begin ()); + + // <- SYNCHRONIZED +} + +void NumberedCollection::impl_cleanUpDeadItems ( TNumberedItemHash& lItems , + const TDeadItemList& lDeadItems) +{ + TDeadItemList::const_iterator pIt; + + for ( pIt = lDeadItems.begin (); + pIt != lDeadItems.end (); + ++pIt ) + { + const long& rDeadItem = *pIt; + lItems.erase(rDeadItem); + } +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/numbers.cxx b/comphelper/source/misc/numbers.cxx new file mode 100644 index 000000000000..47525f5d0c19 --- /dev/null +++ b/comphelper/source/misc/numbers.cxx @@ -0,0 +1,152 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/numbers.hxx> +#include <osl/diagnose.h> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/Locale.hpp> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + +namespace starbeans = ::com::sun::star::beans; +namespace starlang = ::com::sun::star::lang; + +//------------------------------------------------------------------------------ +sal_Int16 getNumberFormatType(const staruno::Reference<starutil::XNumberFormats>& xFormats, sal_Int32 nKey) +{ + sal_Int16 nReturn(starutil::NumberFormat::UNDEFINED); + if (xFormats.is()) + { + try + { + staruno::Reference<starbeans::XPropertySet> xFormat(xFormats->getByKey(nKey)); + if (xFormat.is()) + xFormat->getPropertyValue(rtl::OUString::createFromAscii("Type")) >>= nReturn; + } + catch(...) + { + OSL_TRACE("getNumberFormatType : invalid key! (maybe created with another formatter ?)"); + } + } + return nReturn; +} + +//------------------------------------------------------------------------------ +sal_Int16 getNumberFormatType(const staruno::Reference<starutil::XNumberFormatter>& xFormatter, sal_Int32 nKey) +{ + OSL_ENSURE(xFormatter.is(), "getNumberFormatType : the formatter isn't valid !"); + staruno::Reference<starutil::XNumberFormatsSupplier> xSupplier( xFormatter->getNumberFormatsSupplier()); + OSL_ENSURE(xSupplier.is(), "getNumberFormatType : the formatter doesn't implement a supplier !"); + staruno::Reference<starutil::XNumberFormats> xFormats( xSupplier->getNumberFormats()); + return getNumberFormatType(xFormats, nKey); +} + +//------------------------------------------------------------------------------ +staruno::Any getNumberFormatDecimals(const staruno::Reference<starutil::XNumberFormats>& xFormats, sal_Int32 nKey) +{ + if (xFormats.is()) + { + try + { + staruno::Reference<starbeans::XPropertySet> xFormat( xFormats->getByKey(nKey)); + if (xFormat.is()) + { + static ::rtl::OUString PROPERTY_DECIMALS = ::rtl::OUString::createFromAscii("Decimals"); + return xFormat->getPropertyValue(PROPERTY_DECIMALS); + } + } + catch(...) + { + OSL_TRACE("getNumberFormatDecimals : invalid key! (may be created with another formatter ?)"); + } + } + return staruno::makeAny((sal_Int16)0); +} + + +//------------------------------------------------------------------------------ +sal_Int32 getStandardFormat( + const staruno::Reference<starutil::XNumberFormatter>& xFormatter, + sal_Int16 nType, + const starlang::Locale& _rLocale) +{ + staruno::Reference<starutil::XNumberFormatsSupplier> xSupplier( xFormatter.is() ? xFormatter->getNumberFormatsSupplier() : staruno::Reference<starutil::XNumberFormatsSupplier>(NULL)); + staruno::Reference<starutil::XNumberFormats> xFormats( xSupplier.is() ? xSupplier->getNumberFormats() : staruno::Reference<starutil::XNumberFormats>(NULL)); + staruno::Reference<starutil::XNumberFormatTypes> xTypes(xFormats, staruno::UNO_QUERY); + OSL_ENSURE(xTypes.is(), "getStandardFormat : no format types !"); + + return xTypes.is() ? xTypes->getStandardFormat(nType, _rLocale) : 0; +} + +//------------------------------------------------------------------------------ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; + +//------------------------------------------------------------------------------ +Any getNumberFormatProperty( const Reference< XNumberFormatter >& _rxFormatter, sal_Int32 _nKey, const rtl::OUString& _rPropertyName ) +{ + Any aReturn; + + OSL_ENSURE( _rxFormatter.is() && _rPropertyName.getLength(), "getNumberFormatProperty: invalid arguments!" ); + try + { + Reference< XNumberFormatsSupplier > xSupplier; + Reference< XNumberFormats > xFormats; + Reference< XPropertySet > xFormatProperties; + + if ( _rxFormatter.is() ) + xSupplier = _rxFormatter->getNumberFormatsSupplier(); + if ( xSupplier.is() ) + xFormats = xSupplier->getNumberFormats(); + if ( xFormats.is() ) + xFormatProperties = xFormats->getByKey( _nKey ); + + if ( xFormatProperties.is() ) + aReturn = xFormatProperties->getPropertyValue( _rPropertyName ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "::getNumberFormatProperty: caught an exception (did you create the key with another formatter?)!" ); + } + + return aReturn; +} + +//......................................................................... +} // namespace comphelper +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/officeresourcebundle.cxx b/comphelper/source/misc/officeresourcebundle.cxx new file mode 100644 index 000000000000..0703f8e46d7c --- /dev/null +++ b/comphelper/source/misc/officeresourcebundle.cxx @@ -0,0 +1,243 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/officeresourcebundle.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/resource/XResourceBundle.hpp> +#include <com/sun/star/resource/XResourceBundleLoader.hpp> +#include <com/sun/star/lang/NullPointerException.hpp> +/** === end UNO includes === **/ +#include <osl/mutex.hxx> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using com::sun::star::resource::XResourceBundle; + using com::sun::star::resource::XResourceBundleLoader; + using com::sun::star::resource::MissingResourceException; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::lang::NullPointerException; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Any; + /** === end UNO using === **/ + + //==================================================================== + //= ResourceBundle_Impl + //==================================================================== + class ResourceBundle_Impl + { + private: + Reference< XComponentContext > m_xContext; + ::rtl::OUString m_sBaseName; + Reference< XResourceBundle > m_xBundle; + bool m_bAttemptedCreate; + mutable ::osl::Mutex m_aMutex; + + public: + ResourceBundle_Impl( const Reference< XComponentContext >& _context, const ::rtl::OUString& _baseName ) + :m_xContext( _context ) + ,m_sBaseName( _baseName ) + ,m_bAttemptedCreate( false ) + { + } + + public: + /** loads the string with the given resource id from the resource bundle + @param _resourceId + the id of the string to load + @return + the requested resource string. If no string with the given id exists in the resource bundle, + an empty string is returned. In a non-product version, an OSL_ENSURE will notify you of this + then. + */ + ::rtl::OUString loadString( sal_Int32 _resourceId ) const; + + /** determines whether the resource bundle has a string with the given id + @param _resourceId + the id of the string whose existence is to be checked + @return + <TRUE/> if and only if a string with the given ID exists in the resource + bundle. + */ + bool hasString( sal_Int32 _resourceId ) const; + + private: + /** loads the bundle represented by the instance + + The method is safe against multiple calls: If a previos call succeeded or failed, the + previous result will be returned, without any other processing. + + @precond + Our mutex is locked. + */ + bool impl_loadBundle_nothrow(); + + /** returns the resource bundle key for a string with a given resource id + */ + static ::rtl::OUString + impl_getStringResourceKey( sal_Int32 _resourceId ); + }; + + //-------------------------------------------------------------------- + ::rtl::OUString ResourceBundle_Impl::impl_getStringResourceKey( sal_Int32 _resourceId ) + { + ::rtl::OUStringBuffer key; + key.appendAscii( "string:" ); + key.append( _resourceId ); + return key.makeStringAndClear(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString ResourceBundle_Impl::loadString( sal_Int32 _resourceId ) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString sString; + + if ( const_cast< ResourceBundle_Impl* >( this )->impl_loadBundle_nothrow() ) + { + try + { + OSL_VERIFY( m_xBundle->getByName( impl_getStringResourceKey( _resourceId ) ) >>= sString ); + } + catch( const Exception& ) + { + OSL_ENSURE( false, "ResourceBundle_Impl::loadString: caught an exception!" ); + } + } + return sString; + } + + //-------------------------------------------------------------------- + bool ResourceBundle_Impl::hasString( sal_Int32 _resourceId ) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + bool has = false; + + if ( const_cast< ResourceBundle_Impl* >( this )->impl_loadBundle_nothrow() ) + { + try + { + has = m_xBundle->hasByName( impl_getStringResourceKey( _resourceId ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( false, "ResourceBundle_Impl::hasString: caught an exception!" ); + } + } + return has; + } + + //-------------------------------------------------------------------- + bool ResourceBundle_Impl::impl_loadBundle_nothrow() + { + if ( m_bAttemptedCreate ) + return m_xBundle.is(); + + m_bAttemptedCreate = true; + + Reference< XResourceBundleLoader > xLoader; + try + { + Any aValue( m_xContext->getValueByName( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.resource.OfficeResourceLoader" ) ) ) ); + OSL_VERIFY( aValue >>= xLoader ); + } + catch( const Exception& ) + { + OSL_ENSURE( false, "ResourceBundle_Impl::impl_loadBundle_nopthrow: could not create the resource loader!" ); + } + + if ( !xLoader.is() ) + return false; + + try + { + m_xBundle = xLoader->loadBundle_Default( m_sBaseName ); + } + catch( const MissingResourceException& ) + { + OSL_ENSURE( false, "ResourceBundle_Impl::impl_loadBundle_nopthrow: missing the given resource bundle!" ); + } + + return m_xBundle.is(); + } + + //==================================================================== + //= OfficeResourceBundle + //==================================================================== + //-------------------------------------------------------------------- + OfficeResourceBundle::OfficeResourceBundle( const Reference< XComponentContext >& _context, const ::rtl::OUString& _bundleBaseName ) + :m_pImpl( new ResourceBundle_Impl( _context, _bundleBaseName ) ) + { + if ( !_context.is() ) + throw NullPointerException(); + } + + //-------------------------------------------------------------------- + OfficeResourceBundle::OfficeResourceBundle( const Reference< XComponentContext >& _context, const sal_Char* _bundleBaseAsciiName ) + :m_pImpl( new ResourceBundle_Impl( _context, ::rtl::OUString::createFromAscii( _bundleBaseAsciiName ) ) ) + { + if ( !_context.is() ) + throw NullPointerException(); + } + + //-------------------------------------------------------------------- + OfficeResourceBundle::~OfficeResourceBundle() + { + } + + //-------------------------------------------------------------------- + ::rtl::OUString OfficeResourceBundle::loadString( sal_Int32 _resourceId ) const + { + return m_pImpl->loadString( _resourceId ); + } + + //-------------------------------------------------------------------- + bool OfficeResourceBundle::hasString( sal_Int32 _resourceId ) const + { + return m_pImpl->hasString( _resourceId ); + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/officerestartmanager.cxx b/comphelper/source/misc/officerestartmanager.cxx new file mode 100644 index 000000000000..774918ca992e --- /dev/null +++ b/comphelper/source/misc/officerestartmanager.cxx @@ -0,0 +1,213 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/awt/XRequestCallback.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <comphelper_module.hxx> +#include "officerestartmanager.hxx" + +using namespace ::com::sun::star; + +namespace comphelper +{ + +// ---------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OOfficeRestartManager::getSupportedServiceNames_static() +{ + uno::Sequence< rtl::OUString > aResult( 1 ); + aResult[0] = getServiceName_static(); + return aResult; +} + +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OOfficeRestartManager::getImplementationName_static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.task.OfficeRestartManager" ) ); +} + +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OOfficeRestartManager::getSingletonName_static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ); +} + +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OOfficeRestartManager::getServiceName_static() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.task.OfficeRestartManager" ) ); +} + +// ---------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OOfficeRestartManager::Create( const uno::Reference< uno::XComponentContext >& rxContext ) +{ + return static_cast< cppu::OWeakObject* >( new OOfficeRestartManager( rxContext ) ); +} + +// XRestartManager +// ---------------------------------------------------------- +void SAL_CALL OOfficeRestartManager::requestRestart( const uno::Reference< task::XInteractionHandler >& /* xInteractionHandler */ ) + throw (uno::Exception, uno::RuntimeException) +{ + if ( !m_xContext.is() ) + throw uno::RuntimeException(); + + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // if the restart already running there is no need to trigger it again + if ( m_bRestartRequested ) + return; + + m_bRestartRequested = sal_True; + + // the office is still not initialized, no need to terminate, changing the state is enough + if ( !m_bOfficeInitialized ) + return; + } + + // TODO: use InteractionHandler to report errors + try + { + // register itself as a job that should be executed asynchronously + uno::Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager(), uno::UNO_SET_THROW ); + + uno::Reference< awt::XRequestCallback > xRequestCallback( + xFactory->createInstanceWithContext( + ::rtl::OUString::createFromAscii("com.sun.star.awt.AsyncCallback"), + m_xContext ), + uno::UNO_QUERY_THROW ); + + xRequestCallback->addCallback( this, uno::Any() ); + } + catch ( uno::Exception& ) + { + // the try to request restart has failed + m_bRestartRequested = sal_False; + } +} + +// ---------------------------------------------------------- +::sal_Bool SAL_CALL OOfficeRestartManager::isRestartRequested( ::sal_Bool bOfficeInitialized ) + throw (uno::Exception, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( bOfficeInitialized && !m_bOfficeInitialized ) + m_bOfficeInitialized = bOfficeInitialized; + + return m_bRestartRequested; +} + +// XCallback +// ---------------------------------------------------------- +void SAL_CALL OOfficeRestartManager::notify( const uno::Any& /* aData */ ) + throw ( uno::RuntimeException ) +{ + try + { + sal_Bool bSuccess = sal_False; + + if ( m_xContext.is() ) + { + uno::Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager(), uno::UNO_SET_THROW ); + uno::Reference< frame::XDesktop > xDesktop( + xFactory->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ), m_xContext ), + uno::UNO_QUERY_THROW ); + + // Turn Quickstarter veto off + uno::Reference< beans::XPropertySet > xPropertySet( xDesktop, uno::UNO_QUERY_THROW ); + ::rtl::OUString aVetoPropName( RTL_CONSTASCII_USTRINGPARAM( "SuspendQuickstartVeto" ) ); + uno::Any aValue; + aValue <<= (sal_Bool)sal_True; + xPropertySet->setPropertyValue( aVetoPropName, aValue ); + + try + { + bSuccess = xDesktop->terminate(); + } catch( uno::Exception& ) + {} + + if ( !bSuccess ) + { + aValue <<= (sal_Bool)sal_False; + xPropertySet->setPropertyValue( aVetoPropName, aValue ); + } + } + + if ( !bSuccess ) + m_bRestartRequested = sal_False; + } + catch( uno::Exception& ) + { + // the try to restart has failed + m_bRestartRequested = sal_False; + } +} + +// XServiceInfo +// ---------------------------------------------------------- +::rtl::OUString SAL_CALL OOfficeRestartManager::getImplementationName() throw (uno::RuntimeException) +{ + return getImplementationName_static(); +} + +// ---------------------------------------------------------- +::sal_Bool SAL_CALL OOfficeRestartManager::supportsService( const ::rtl::OUString& aServiceName ) throw (uno::RuntimeException) +{ + const uno::Sequence< rtl::OUString > & aSupportedNames = getSupportedServiceNames_static(); + for ( sal_Int32 nInd = 0; nInd < aSupportedNames.getLength(); nInd++ ) + { + if ( aSupportedNames[ nInd ].equals( aServiceName ) ) + return sal_True; + } + + return sal_False; +} + +// ---------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OOfficeRestartManager::getSupportedServiceNames() throw (uno::RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +} // namespace comphelper + +void createRegistryInfo_OOfficeRestartManager() +{ + static ::comphelper::module::OAutoRegistration< ::comphelper::OOfficeRestartManager > aAutoRegistration; + static ::comphelper::module::OSingletonRegistration< ::comphelper::OOfficeRestartManager > aSingletonRegistration; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/officerestartmanager.hxx b/comphelper/source/misc/officerestartmanager.hxx new file mode 100644 index 000000000000..1fe44d681c59 --- /dev/null +++ b/comphelper/source/misc/officerestartmanager.hxx @@ -0,0 +1,93 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __OFFICESTARTMANAGER_HXX_ +#define __OFFICESTARTMANAGER_HXX_ + +#include <com/sun/star/task/XRestartManager.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/awt/XCallback.hpp> + +#include <osl/mutex.hxx> +#include <cppuhelper/implbase3.hxx> + +namespace comphelper +{ + +class OOfficeRestartManager : public ::cppu::WeakImplHelper3< ::com::sun::star::task::XRestartManager + , ::com::sun::star::awt::XCallback + , ::com::sun::star::lang::XServiceInfo > +{ + ::osl::Mutex m_aMutex; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + + sal_Bool m_bOfficeInitialized; + sal_Bool m_bRestartRequested; + +public: + OOfficeRestartManager( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext ) + : m_xContext( xContext ) + , m_bOfficeInitialized( sal_False ) + , m_bRestartRequested( sal_False ) + {} + + virtual ~OOfficeRestartManager() + {} + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames_static(); + + static ::rtl::OUString SAL_CALL getImplementationName_static(); + + static ::rtl::OUString SAL_CALL getSingletonName_static(); + + static ::rtl::OUString SAL_CALL getServiceName_static(); + + 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 >& rxContext ); + +// XRestartManager + virtual void SAL_CALL requestRestart( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xInteractionHandler ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isRestartRequested( ::sal_Bool bInitialized ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + +// XCallback + virtual void SAL_CALL notify( const ::com::sun::star::uno::Any& aData ) throw (::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); + +}; + +} // namespace comphelper + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/proxyaggregation.cxx b/comphelper/source/misc/proxyaggregation.cxx new file mode 100644 index 000000000000..19307d794ff6 --- /dev/null +++ b/comphelper/source/misc/proxyaggregation.cxx @@ -0,0 +1,278 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/proxyaggregation.hxx> +#include <com/sun/star/reflection/XProxyFactory.hpp> + +//............................................................................. +namespace comphelper +{ +//............................................................................. + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::reflection; + + //========================================================================= + //= OProxyAggregation + //========================================================================= + //------------------------------------------------------------------------- + OProxyAggregation::OProxyAggregation( const Reference< XMultiServiceFactory >& _rxORB ) + :m_xORB( _rxORB ) + { + } + + //------------------------------------------------------------------------- + void OProxyAggregation::baseAggregateProxyFor( const Reference< XInterface >& _rxComponent, oslInterlockedCount& _rRefCount, + ::cppu::OWeakObject& _rDelegator ) + { + // first a factory for the proxy + Reference< XProxyFactory > xFactory( + m_xORB->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.ProxyFactory" ) ) ), + UNO_QUERY + ); + OSL_ENSURE( xFactory.is(), "OProxyAggregation::baseAggregateProxyFor: could not create a proxy factory!" ); + + // then the proxy itself + if ( xFactory.is() ) + { + { // i36686 OJ: achieve the desctruction of the tempoary -> otherwise it leads to _rRefCount -= 2 + m_xProxyAggregate = xFactory->createProxy( _rxComponent ); + } + if ( m_xProxyAggregate.is() ) + m_xProxyAggregate->queryAggregation( ::getCppuType( &m_xProxyTypeAccess ) ) >>= m_xProxyTypeAccess; + + // aggregate the proxy + osl_incrementInterlockedCount( &_rRefCount ); + if ( m_xProxyAggregate.is() ) + { + // At this point in time, the proxy has a ref count of exactly two - in m_xControlContextProxy, + // and in m_xProxyTypeAccess. + // Remember to _not_ reset these members unless the delegator of the proxy has been reset, too! + m_xProxyAggregate->setDelegator( _rDelegator ); + } + osl_decrementInterlockedCount( &_rRefCount ); + } + } + + //------------------------------------------------------------------------- + Any SAL_CALL OProxyAggregation::queryAggregation( const Type& _rType ) throw (RuntimeException) + { + return m_xProxyAggregate.is() ? m_xProxyAggregate->queryAggregation( _rType ) : Any(); + } + + //------------------------------------------------------------------------- + Sequence< Type > SAL_CALL OProxyAggregation::getTypes( ) throw (RuntimeException) + { + Sequence< Type > aTypes; + if ( m_xProxyAggregate.is() ) + { + if ( m_xProxyTypeAccess.is() ) + aTypes = m_xProxyTypeAccess->getTypes(); + } + return aTypes; + } + + //------------------------------------------------------------------------- + OProxyAggregation::~OProxyAggregation() + { + if ( m_xProxyAggregate.is() ) + m_xProxyAggregate->setDelegator( NULL ); + m_xProxyAggregate.clear(); + m_xProxyTypeAccess.clear(); + // this should remove the _two_only_ "real" references (means not delegated to + // ourself) to this proxy, and thus delete it + } + + //========================================================================= + //= OComponentProxyAggregationHelper + //========================================================================= + //------------------------------------------------------------------------- + OComponentProxyAggregationHelper::OComponentProxyAggregationHelper( const Reference< XMultiServiceFactory >& _rxORB, + ::cppu::OBroadcastHelper& _rBHelper ) + :OProxyAggregation( _rxORB ) + ,m_rBHelper( _rBHelper ) + { + OSL_ENSURE( _rxORB.is(), "OComponentProxyAggregationHelper::OComponentProxyAggregationHelper: invalid arguments!" ); + } + + //------------------------------------------------------------------------- + void OComponentProxyAggregationHelper::componentAggregateProxyFor( + const Reference< XComponent >& _rxComponent, oslInterlockedCount& _rRefCount, + ::cppu::OWeakObject& _rDelegator ) + { + OSL_ENSURE( _rxComponent.is(), "OComponentProxyAggregationHelper::componentAggregateProxyFor: invalid inner component!" ); + m_xInner = _rxComponent; + + // aggregate a proxy for the object + baseAggregateProxyFor( m_xInner.get(), _rRefCount, _rDelegator ); + + // add as event listener to the inner context, because we want to be notified of disposals + osl_incrementInterlockedCount( &_rRefCount ); + { + if ( m_xInner.is() ) + m_xInner->addEventListener( this ); + } + osl_decrementInterlockedCount( &_rRefCount ); + } + + //------------------------------------------------------------------------- + Any SAL_CALL OComponentProxyAggregationHelper::queryInterface( const Type& _rType ) throw (RuntimeException) + { + Any aReturn( BASE::queryInterface( _rType ) ); + if ( !aReturn.hasValue() ) + aReturn = OProxyAggregation::queryAggregation( _rType ); + return aReturn; + } + + //------------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OComponentProxyAggregationHelper, BASE, OProxyAggregation ) + + //------------------------------------------------------------------------- + OComponentProxyAggregationHelper::~OComponentProxyAggregationHelper( ) + { + OSL_ENSURE( m_rBHelper.bDisposed, "OComponentProxyAggregationHelper::~OComponentProxyAggregationHelper: you should dispose your derived class in the dtor, if necessary!" ); + // if this asserts, add the following to your derived class dtor: + // + // if ( !m_rBHelper.bDisposed ) + // { + // acquire(); // to prevent duplicate dtor calls + // dispose(); + // } + + m_xInner.clear(); + } + + //------------------------------------------------------------------------- + void SAL_CALL OComponentProxyAggregationHelper::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + if ( _rSource.Source == m_xInner ) + { // it's our inner context which is dying -> dispose ourself + if ( !m_rBHelper.bDisposed && !m_rBHelper.bInDispose ) + { // (if necessary only, of course) + dispose(); + } + } + } + + //------------------------------------------------------------------------- + void SAL_CALL OComponentProxyAggregationHelper::dispose() throw( RuntimeException ) + { + ::osl::MutexGuard aGuard( m_rBHelper.rMutex ); + + // dispose our inner context + // before we do this, remove ourself as listener - else in disposing( EventObject ), we + // would dispose ourself a second time + Reference< XComponent > xComp( m_xInner, UNO_QUERY ); + if ( xComp.is() ) + { + xComp->removeEventListener( this ); + xComp->dispose(); + xComp.clear(); + } + } + + //========================================================================= + //= OComponentProxyAggregation + //========================================================================= + //------------------------------------------------------------------------- + OComponentProxyAggregation::OComponentProxyAggregation( const Reference< XMultiServiceFactory >& _rxORB, + const Reference< XComponent >& _rxComponent ) + :OComponentProxyAggregation_CBase( m_aMutex ) + ,OComponentProxyAggregationHelper( _rxORB, rBHelper ) + { + OSL_ENSURE( _rxComponent.is(), "OComponentProxyAggregation::OComponentProxyAggregation: accessible is no XComponent!" ); + if ( _rxComponent.is() ) + componentAggregateProxyFor( _rxComponent, m_refCount, *this ); + } + + //------------------------------------------------------------------------- + OComponentProxyAggregation::~OComponentProxyAggregation() + { + implEnsureDisposeInDtor( ); + } + + //------------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OComponentProxyAggregation, OComponentProxyAggregation_CBase, OComponentProxyAggregationHelper ) + + //------------------------------------------------------------------------- + IMPLEMENT_GET_IMPLEMENTATION_ID( OComponentProxyAggregation ) + + //------------------------------------------------------------------------- + Sequence< Type > SAL_CALL OComponentProxyAggregation::getTypes( ) throw (RuntimeException) + { + Sequence< Type > aTypes( OComponentProxyAggregationHelper::getTypes() ); + + // append XComponent, coming from OComponentProxyAggregation_CBase + sal_Int32 nLen = aTypes.getLength(); + aTypes.realloc( nLen + 1 ); + aTypes[ nLen ] = ::getCppuType( static_cast< Reference< XComponent >* >( NULL ) ); + + return aTypes; + } + + //------------------------------------------------------------------------- + void OComponentProxyAggregation::implEnsureDisposeInDtor( ) + { + if ( !rBHelper.bDisposed ) + { + acquire(); // to prevent duplicate dtor calls + dispose(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OComponentProxyAggregation::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + // simly disambiguate - this is necessary for MSVC to distinguish + // "disposing( EventObject )" from "disposing()" + OComponentProxyAggregationHelper::disposing( _rSource ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OComponentProxyAggregation::disposing() throw (RuntimeException) + { + // call the dispose-functionality of the base, which will dispose our aggregated component + OComponentProxyAggregationHelper::dispose(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OComponentProxyAggregation::dispose() throw( RuntimeException ) + { + // simply disambiguate + OComponentProxyAggregation_CBase::dispose(); + } + + +//............................................................................. +} // namespace comphelper +//............................................................................. + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/querydeep.cxx b/comphelper/source/misc/querydeep.cxx new file mode 100644 index 000000000000..348d038383c2 --- /dev/null +++ b/comphelper/source/misc/querydeep.cxx @@ -0,0 +1,78 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/querydeep.hxx> +#include <typelib/typedescription.h> + +//__________________________________________________________________________________________________ + +sal_Bool comphelper::isDerivedFrom( + const ::com::sun::star::uno::Type & rBaseType, + const ::com::sun::star::uno::Type & rType ) +{ + using namespace ::com::sun::star::uno; + + TypeClass eClass = rBaseType.getTypeClass(); + + if (eClass != TypeClass_INTERFACE) + return sal_False; + + // supported TypeClass - do the types match ? + if (eClass != rType.getTypeClass()) + return sal_False; + + sal_Bool bRet; + + // shortcut for simple case + if (rBaseType == ::getCppuType(static_cast<const Reference< XInterface > *>(0))) + { + bRet = sal_True; + } + else + { + // now ask in cppu (aka typelib) + ::typelib_TypeDescription *pBaseTD = 0, *pTD = 0; + + rBaseType. getDescription(&pBaseTD); + rType. getDescription(&pTD); + + // interfaces are assignable to a base + bRet = ::typelib_typedescription_isAssignableFrom(pBaseTD, pTD); + + ::typelib_typedescription_release(pBaseTD); + ::typelib_typedescription_release(pTD); + } + + return bRet; +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/regpathhelper.cxx b/comphelper/source/misc/regpathhelper.cxx new file mode 100644 index 000000000000..7fa3548cf744 --- /dev/null +++ b/comphelper/source/misc/regpathhelper.cxx @@ -0,0 +1,234 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include <stdio.h> +#include <osl/file.hxx> +#include <osl/security.hxx> +#include <osl/thread.h> +#include <osl/process.h> +#include <rtl/textenc.h> +#include <rtl/uri.h> +#include <rtl/uri.hxx> + +using namespace osl; +using namespace rtl; + +#define PATH_DELEMITTER '/' + +#define USER_REGISTRY_NAME_ENV "STAR_USER_REGISTRY" +#define SYSTEM_REGISTRY_NAME_ENV "STAR_REGISTRY" +#define REGISTRY_SYSTEM_NAME "services.rdb" + +#define REGISTRY_LOCAL_NAME "user60.rdb" + +#ifdef SAL_UNX +#define CONFIG_PATH_PREFIX "." +#else +#define CONFIG_PATH_PREFIX "" +#endif + +namespace comphelper +{ + +/** + @return sal_True, if the office is started in a portal + environment. + sal_False, if the common office is started + */ +static sal_Bool retrievePortalUserDir( OUString *pDirectory ) +{ + sal_uInt32 nArgs = osl_getCommandArgCount(); + sal_Bool bIsPortalUser = sal_False; + OUString sArg; + while( nArgs > 0 ) + { + if ( !osl_getCommandArg(--nArgs, &sArg.pData) ) + { + if ( sArg.indexOf(OUString::createFromAscii("-userid")) == 0 ) + { + + bIsPortalUser = sal_True; + sal_Int32 nStart = sArg.lastIndexOf( '[' ); + sal_Int32 nEnd = sArg.lastIndexOf( ']' ); + if( -1 == nStart || -1 == nEnd || nEnd < nStart) + { + *pDirectory = OUString(); + } + else + { + OUString aEncHome = sArg.copy( nStart + 1 , nEnd - nStart -1 ); + *pDirectory = rtl::Uri::decode(aEncHome, + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8); + } + break; + } + } + } + return bIsPortalUser; +} + + +static OUString getDefaultLocalRegistry() +{ + OUString uBuffer, userRegistryName; + OUString portalUserDir; + + sal_Bool bIsPortalUser = retrievePortalUserDir( &portalUserDir ); + + if ( bIsPortalUser ) + { + if( portalUserDir.getLength() ) + { + FileBase::getFileURLFromSystemPath( portalUserDir , portalUserDir ); + userRegistryName = portalUserDir; + userRegistryName += OUString( RTL_CONSTASCII_USTRINGPARAM( + "/user/" REGISTRY_LOCAL_NAME ) ); + + // Directory creation is probably necessary for bootstrapping a new + // user in the portal environment (the ucb uses this function). + // This should be solved differently, as + // no one expects this function to create anything ... + OUString sSeparator(RTL_CONSTASCII_USTRINGPARAM("/")); + OUString sPath(RTL_CONSTASCII_USTRINGPARAM("file://")); + FileBase::RC retRC = FileBase::E_None; + + sal_Int32 nIndex = 3; + sPath += userRegistryName.getToken(2, '/', nIndex); + while( nIndex != -1 ) + { + sPath += sSeparator; + sPath += userRegistryName.getToken(0, '/', nIndex); + if( nIndex == -1 ) + break; + Directory aDir( sPath ); + if( aDir.open() == FileBase::E_NOENT ) + { + retRC = Directory::create(sPath); + if ( retRC != FileBase::E_None && retRC != FileBase::E_EXIST) + { + return OUString(); + } + } + } + } + } + else /* bIsPortalUser */ + { + ::osl::Security aUserSecurity; + aUserSecurity.getConfigDir( userRegistryName ); + userRegistryName += OUString( RTL_CONSTASCII_USTRINGPARAM( + "/" CONFIG_PATH_PREFIX REGISTRY_LOCAL_NAME ) ); + } + + return userRegistryName; +} + + +OUString getPathToUserRegistry() +{ + OUString userRegistryName; + FILE *f=NULL; + + // search the environment STAR_USER_REGISTRY + OString sBuffer( getenv(USER_REGISTRY_NAME_ENV) ); + if ( sBuffer.getLength() > 0 ) + { + f = fopen( sBuffer.getStr(), "r" ); + + if (f != NULL) + { + fclose(f); + userRegistryName = OStringToOUString( sBuffer, osl_getThreadTextEncoding() ); + } + } + + if ( !userRegistryName.getLength() ) + { + userRegistryName = getDefaultLocalRegistry(); + } + + return userRegistryName; +} + +OUString getPathToSystemRegistry() +{ + OUString uBuffer; + OUString registryBaseName( RTL_CONSTASCII_USTRINGPARAM(REGISTRY_SYSTEM_NAME) ); + OUString systemRegistryName; + FILE *f=NULL; + + // search in the directory of the executable + if(osl_Process_E_None == osl_getExecutableFile(&uBuffer.pData)) + { + sal_uInt32 lastIndex = uBuffer.lastIndexOf(PATH_DELEMITTER); + if (lastIndex > 0) + { + uBuffer = uBuffer.copy(0, lastIndex + 1); + } + + uBuffer += registryBaseName; + + if (!FileBase::getSystemPathFromFileURL(uBuffer, systemRegistryName)) + { + OString tmpStr( OUStringToOString(systemRegistryName, osl_getThreadTextEncoding()) ); + f = fopen( tmpStr.getStr(), "r" ); + } + } + + if (f == NULL) + { + // search the environment STAR_REGISTRY + OString tmpStr( getenv(SYSTEM_REGISTRY_NAME_ENV) ); + if ( tmpStr.getLength() > 0 ) + { + f = fopen(tmpStr.getStr(), "r"); + + if (f != NULL) + { + fclose(f); + systemRegistryName = OStringToOUString( tmpStr, osl_getThreadTextEncoding() ); + } else + { + systemRegistryName = OUString(); + } + } + } else + { + fclose(f); + } + + return systemRegistryName; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/scopeguard.cxx b/comphelper/source/misc/scopeguard.cxx new file mode 100644 index 000000000000..c194e98e5e8d --- /dev/null +++ b/comphelper/source/misc/scopeguard.cxx @@ -0,0 +1,73 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/scopeguard.hxx" +#include "osl/diagnose.h" +#include "com/sun/star/uno/Exception.hpp" + +namespace comphelper { + +ScopeGuard::~ScopeGuard() +{ + if (m_func) + { + if (m_excHandling == IGNORE_EXCEPTIONS) + { + try { + m_func(); + } + catch (com::sun::star::uno::Exception & exc) { + (void) exc; // avoid warning about unused variable + OSL_ENSURE( + false, rtl::OUStringToOString( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "UNO exception occured: ") ) + + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + catch (...) { + OSL_ENSURE( false, "unknown exception occured!" ); + } + } + else + { + m_func(); + } + } +} + +void ScopeGuard::dismiss() +{ + m_func.clear(); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/sequence.cxx b/comphelper/source/misc/sequence.cxx new file mode 100644 index 000000000000..bc264bf87569 --- /dev/null +++ b/comphelper/source/misc/sequence.cxx @@ -0,0 +1,105 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/sequence.hxx> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + +//------------------------------------------------------------------------------ +staruno::Sequence<sal_Int16> findValue(const staruno::Sequence< ::rtl::OUString >& _rList, const ::rtl::OUString& _rValue, sal_Bool _bOnlyFirst) +{ + sal_Int32 nLength = _rList.getLength(); + + if( _bOnlyFirst ) + { + ////////////////////////////////////////////////////////////////////// + // An welcher Position finde ich den Wert? + sal_Int32 nPos = -1; + const ::rtl::OUString* pTArray = _rList.getConstArray(); + for (sal_Int32 i = 0; i < nLength; ++i, ++pTArray) + { + if( pTArray->equals(_rValue) ) + { + nPos = i; + break; + } + } + + ////////////////////////////////////////////////////////////////////// + // Sequence fuellen + if( nPos>-1 ) + { + staruno::Sequence<sal_Int16> aRetSeq( 1 ); + aRetSeq.getArray()[0] = (sal_Int16)nPos; + + return aRetSeq; + } + + return staruno::Sequence<sal_Int16>(); + + } + else + { + staruno::Sequence<sal_Int16> aRetSeq( nLength ); + sal_Int16* pReturn = aRetSeq.getArray(); + + ////////////////////////////////////////////////////////////////////// + // Wie oft kommt der Wert vor? + const ::rtl::OUString* pTArray = _rList.getConstArray(); + for (sal_Int32 i = 0; i < nLength; ++i, ++pTArray) + { + if( pTArray->equals(_rValue) ) + { + *pReturn = (sal_Int16)i; + ++pReturn; + } + } + + aRetSeq.realloc(pReturn - aRetSeq.getArray()); + + return aRetSeq; + } +} +// ----------------------------------------------------------------------------- +sal_Bool existsValue(const ::rtl::OUString& Value,const staruno::Sequence< ::rtl::OUString >& _aList) +{ + const ::rtl::OUString * pIter = _aList.getConstArray(); + const ::rtl::OUString * pEnd = pIter + _aList.getLength(); + return ::std::find(pIter,pEnd,Value) != pEnd; +} + +//......................................................................... +} // namespace comphelper +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/sequenceashashmap.cxx b/comphelper/source/misc/sequenceashashmap.cxx new file mode 100644 index 000000000000..ea583797ee2a --- /dev/null +++ b/comphelper/source/misc/sequenceashashmap.cxx @@ -0,0 +1,403 @@ +/* -*- 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 + * <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_comphelper.hxx" + +//_______________________________________________ +// includes +#include <comphelper/sequenceashashmap.hxx> + +//_______________________________________________ +// namespace + +namespace comphelper{ + +namespace css = ::com::sun::star; + +//_______________________________________________ +// definitions + +/*----------------------------------------------- + 04.11.2003 09:29 +-----------------------------------------------*/ +SequenceAsHashMap::SequenceAsHashMap() + : SequenceAsHashMapBase() +{ +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +SequenceAsHashMap::SequenceAsHashMap(const css::uno::Any& aSource) +{ + (*this) << aSource; +} + +//----------------------------------------------- +SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::uno::Any >& lSource) +{ + (*this) << lSource; +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::beans::PropertyValue >& lSource) +{ + (*this) << lSource; +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence< css::beans::NamedValue >& lSource) +{ + (*this) << lSource; +} + +/*----------------------------------------------- + 04.11.2003 09:04 +-----------------------------------------------*/ +SequenceAsHashMap::~SequenceAsHashMap() +{ +} + +/*----------------------------------------------- + 04.11.2003 10:21 +-----------------------------------------------*/ +void SequenceAsHashMap::operator<<(const css::uno::Any& aSource) +{ + // An empty Any reset this instance! + if (!aSource.hasValue()) + { + clear(); + return; + } + + css::uno::Sequence< css::beans::NamedValue > lN; + if (aSource >>= lN) + { + (*this) << lN; + return; + } + + css::uno::Sequence< css::beans::PropertyValue > lP; + if (aSource >>= lP) + { + (*this) << lP; + return; + } + + throw css::beans::IllegalTypeException( + ::rtl::OUString::createFromAscii("Any contains wrong type."), + css::uno::Reference< css::uno::XInterface >()); +} + +//----------------------------------------------- +void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::uno::Any >& lSource) +{ + sal_Int32 c = lSource.getLength(); + sal_Int32 i = 0; + + for (i=0; i<c; ++i) + { + css::beans::PropertyValue lP; + if (lSource[i] >>= lP) + { + if ( + (!lP.Name.getLength()) || + (!lP.Value.hasValue()) + ) + throw css::beans::IllegalTypeException( + ::rtl::OUString::createFromAscii("PropertyValue struct contains no usefull informations."), + css::uno::Reference< css::uno::XInterface >()); + (*this)[lP.Name] = lP.Value; + continue; + } + + css::beans::NamedValue lN; + if (lSource[i] >>= lN) + { + if ( + (!lN.Name.getLength()) || + (!lN.Value.hasValue()) + ) + throw css::beans::IllegalTypeException( + ::rtl::OUString::createFromAscii("NamedValue struct contains no usefull informations."), + css::uno::Reference< css::uno::XInterface >()); + (*this)[lN.Name] = lN.Value; + continue; + } + + // ignore VOID Any ... but reject wrong filled ones! + if (lSource[i].hasValue()) + throw css::beans::IllegalTypeException( + ::rtl::OUString::createFromAscii("Any contains wrong type."), + css::uno::Reference< css::uno::XInterface >()); + } +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::PropertyValue >& lSource) +{ + clear(); + + sal_Int32 c = lSource.getLength(); + const css::beans::PropertyValue* pSource = lSource.getConstArray(); + + for (sal_Int32 i=0; i<c; ++i) + (*this)[pSource[i].Name] = pSource[i].Value; +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::NamedValue >& lSource) +{ + clear(); + + sal_Int32 c = lSource.getLength(); + const css::beans::NamedValue* pSource = lSource.getConstArray(); + + for (sal_Int32 i=0; i<c; ++i) + (*this)[pSource[i].Name] = pSource[i].Value; +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::PropertyValue >& lDestination) const +{ + sal_Int32 c = (sal_Int32)size(); + lDestination.realloc(c); + css::beans::PropertyValue* pDestination = lDestination.getArray(); + + sal_Int32 i = 0; + for (const_iterator pThis = begin(); + pThis != end() ; + ++pThis ) + { + pDestination[i].Name = pThis->first ; + pDestination[i].Value = pThis->second; + ++i; + } +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::NamedValue >& lDestination) const +{ + sal_Int32 c = (sal_Int32)size(); + lDestination.realloc(c); + css::beans::NamedValue* pDestination = lDestination.getArray(); + + sal_Int32 i = 0; + for (const_iterator pThis = begin(); + pThis != end() ; + ++pThis ) + { + pDestination[i].Name = pThis->first ; + pDestination[i].Value = pThis->second; + ++i; + } +} + +/*----------------------------------------------- + 30.07.2007 14:10 +-----------------------------------------------*/ +const css::uno::Any SequenceAsHashMap::getAsConstAny(::sal_Bool bAsPropertyValueList) const +{ + css::uno::Any aDestination; + if (bAsPropertyValueList) + aDestination = css::uno::makeAny(getAsConstPropertyValueList()); + else + aDestination = css::uno::makeAny(getAsConstNamedValueList()); + return aDestination; +} + +/*----------------------------------------------- + 30.07.2007 14:10 +-----------------------------------------------*/ +const css::uno::Sequence< css::uno::Any > SequenceAsHashMap::getAsConstAnyList(::sal_Bool bAsPropertyValueList) const +{ + ::sal_Int32 i = 0; + ::sal_Int32 c = (::sal_Int32)size(); + css::uno::Sequence< css::uno::Any > lDestination(c); + css::uno::Any* pDestination = lDestination.getArray(); + + for (const_iterator pThis = begin(); + pThis != end() ; + ++pThis ) + { + if (bAsPropertyValueList) + { + css::beans::PropertyValue aProp; + aProp.Name = pThis->first; + aProp.Value = pThis->second; + pDestination[i] = css::uno::makeAny(aProp); + } + else + { + css::beans::NamedValue aProp; + aProp.Name = pThis->first; + aProp.Value = pThis->second; + pDestination[i] = css::uno::makeAny(aProp); + } + + ++i; + } + + return lDestination; +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +const css::uno::Sequence< css::beans::NamedValue > SequenceAsHashMap::getAsConstNamedValueList() const +{ + css::uno::Sequence< css::beans::NamedValue > lReturn; + (*this) >> lReturn; + return lReturn; +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +const css::uno::Sequence< css::beans::PropertyValue > SequenceAsHashMap::getAsConstPropertyValueList() const +{ + css::uno::Sequence< css::beans::PropertyValue > lReturn; + (*this) >> lReturn; + return lReturn; +} + +/*----------------------------------------------- + 07.03.2007 12:45 +-----------------------------------------------*/ +sal_Bool SequenceAsHashMap::match(const SequenceAsHashMap& rCheck) const +{ + const_iterator pCheck; + for ( pCheck = rCheck.begin(); + pCheck != rCheck.end() ; + ++pCheck ) + { + const ::rtl::OUString& sCheckName = pCheck->first; + const css::uno::Any& aCheckValue = pCheck->second; + const_iterator pFound = find(sCheckName); + + if (pFound == end()) + return sal_False; + + const css::uno::Any& aFoundValue = pFound->second; + if (aFoundValue != aCheckValue) + return sal_False; + } + + return sal_True; +} + +/*----------------------------------------------- + 30.07.2007 14:30 +-----------------------------------------------*/ +void SequenceAsHashMap::update(const SequenceAsHashMap& rUpdate) +{ + const_iterator pUpdate; + for ( pUpdate = rUpdate.begin(); + pUpdate != rUpdate.end() ; + ++pUpdate ) + { + const ::rtl::OUString& sName = pUpdate->first; + const css::uno::Any& aValue = pUpdate->second; + + (*this)[sName] = aValue; + } +} + +/*----------------------------------------------- + 04.11.2003 08:30 +-----------------------------------------------*/ +#if OSL_DEBUG_LEVEL > 1 +void SequenceAsHashMap::dbg_dumpToFile(const char* pFileName, + const char* pComment ) const +{ + if (!pFileName || !pComment) + return; + + FILE* pFile = fopen(pFileName, "a"); + if (!pFile) + return; + + ::rtl::OUStringBuffer sBuffer(1000); + sBuffer.appendAscii("\n----------------------------------------\n"); + sBuffer.appendAscii(pComment ); + sBuffer.appendAscii("\n----------------------------------------\n"); + sal_Int32 i = 0; + for (const_iterator pIt = begin(); + pIt != end() ; + ++pIt ) + { + sBuffer.appendAscii("[" ); + sBuffer.append (i++ ); + sBuffer.appendAscii("] " ); + sBuffer.appendAscii("\"" ); + sBuffer.append (pIt->first); + sBuffer.appendAscii("\" = \"" ); + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xv; + ::rtl::OUString sv; + sal_Int32 nv; + sal_Bool bv; + + if (pIt->second >>= sv) + sBuffer.append(sv); + else + if (pIt->second >>= nv) + sBuffer.append(nv); + else + if (pIt->second >>= bv) + sBuffer.appendAscii(bv ? "true" : "false"); + else + if (pIt->second >>= xv) + sBuffer.appendAscii(xv.is() ? "object" : "null"); + else + sBuffer.appendAscii("???"); + + sBuffer.appendAscii("\"\n"); + } + + fprintf(pFile, ::rtl::OUStringToOString(sBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8).getStr()); + fclose(pFile); +} +#endif // OSL_DEBUG_LEVEL > 1 + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/servicedecl.cxx b/comphelper/source/misc/servicedecl.cxx new file mode 100644 index 000000000000..85bb01e7d15c --- /dev/null +++ b/comphelper/source/misc/servicedecl.cxx @@ -0,0 +1,198 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/servicedecl.hxx" +#include "osl/diagnose.h" +#include "rtl/string.hxx" +#include "rtl/ustrbuf.hxx" +#include "cppuhelper/implbase2.hxx" +#include "comphelper/sequence.hxx" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include <vector> + +using namespace com::sun::star; + +namespace comphelper { +namespace service_decl { + +class ServiceDecl::Factory : + public cppu::WeakImplHelper2<lang::XSingleComponentFactory, + lang::XServiceInfo>, + private boost::noncopyable +{ +public: + explicit Factory( ServiceDecl const& rServiceDecl ) + : m_rServiceDecl(rServiceDecl) {} + + // XServiceInfo: + virtual rtl::OUString SAL_CALL getImplementationName() + throw (uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( rtl::OUString const& name ) + throw (uno::RuntimeException); + virtual uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() + throw (uno::RuntimeException); + // XSingleComponentFactory: + virtual uno::Reference<uno::XInterface> SAL_CALL createInstanceWithContext( + uno::Reference<uno::XComponentContext> const& xContext ) + throw (uno::Exception); + virtual uno::Reference<uno::XInterface> SAL_CALL + createInstanceWithArgumentsAndContext( + uno::Sequence<uno::Any> const& args, + uno::Reference<uno::XComponentContext> const& xContext ) + throw (uno::Exception); + +private: + virtual ~Factory(); + + ServiceDecl const& m_rServiceDecl; +}; + +ServiceDecl::Factory::~Factory() +{ +} + +// XServiceInfo: +rtl::OUString ServiceDecl::Factory::getImplementationName() + throw (uno::RuntimeException) +{ + return m_rServiceDecl.getImplementationName(); +} + +sal_Bool ServiceDecl::Factory::supportsService( rtl::OUString const& name ) + throw (uno::RuntimeException) +{ + return m_rServiceDecl.supportsService(name); +} + +uno::Sequence<rtl::OUString> ServiceDecl::Factory::getSupportedServiceNames() + throw (uno::RuntimeException) +{ + return m_rServiceDecl.getSupportedServiceNames(); +} + +// XSingleComponentFactory: +uno::Reference<uno::XInterface> ServiceDecl::Factory::createInstanceWithContext( + uno::Reference<uno::XComponentContext> const& xContext ) + throw (uno::Exception) +{ + return m_rServiceDecl.m_createFunc( + m_rServiceDecl, uno::Sequence<uno::Any>(), xContext ); +} + +uno::Reference<uno::XInterface> +ServiceDecl::Factory::createInstanceWithArgumentsAndContext( + uno::Sequence<uno::Any > const& args, + uno::Reference<uno::XComponentContext> const& xContext ) + throw (uno::Exception) +{ + return m_rServiceDecl.m_createFunc( + m_rServiceDecl, args, xContext ); +} + +bool ServiceDecl::writeInfo( registry::XRegistryKey * xKey ) const +{ + bool bRet = false; + if (xKey != 0) { + rtl::OUStringBuffer buf; + buf.append( static_cast<sal_Unicode>('/') ); + buf.appendAscii( m_pImplName ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/UNO/SERVICES") ); + try { + uno::Reference<registry::XRegistryKey> const xNewKey( + xKey->createKey( buf.makeStringAndClear() ) ); + + rtl::OString const str(m_pServiceNames); + sal_Int32 nIndex = 0; + do { + rtl::OString const token( str.getToken( 0, m_cDelim, nIndex ) ); + xNewKey->createKey( + rtl::OUString( token.getStr(), token.getLength(), + RTL_TEXTENCODING_ASCII_US ) ); + } + while (nIndex >= 0); + + bRet = true; + } + catch (registry::InvalidRegistryException const&) { + OSL_ENSURE( false, "### InvalidRegistryException!" ); + } + } + return bRet; +} + +void * ServiceDecl::getFactory( sal_Char const* pImplName ) const +{ + if (rtl_str_compare(m_pImplName, pImplName) == 0) { + lang::XSingleComponentFactory * const pFac( new Factory(*this) ); + pFac->acquire(); + return pFac; + } + return 0; +} + +uno::Sequence<rtl::OUString> ServiceDecl::getSupportedServiceNames() const +{ + std::vector<rtl::OUString> vec; + + rtl::OString const str(m_pServiceNames); + sal_Int32 nIndex = 0; + do { + rtl::OString const token( str.getToken( 0, m_cDelim, nIndex ) ); + vec.push_back( rtl::OUString( token.getStr(), token.getLength(), + RTL_TEXTENCODING_ASCII_US ) ); + } + while (nIndex >= 0); + + return comphelper::containerToSequence(vec); +} + +bool ServiceDecl::supportsService( ::rtl::OUString const& name ) const +{ + rtl::OString const str(m_pServiceNames); + sal_Int32 nIndex = 0; + do { + rtl::OString const token( str.getToken( 0, m_cDelim, nIndex ) ); + if (name.equalsAsciiL( token.getStr(), token.getLength() )) + return true; + } + while (nIndex >= 0); + return false; +} + +rtl::OUString ServiceDecl::getImplementationName() const +{ + return rtl::OUString::createFromAscii(m_pImplName); +} + +} // namespace service_decl +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/serviceinfohelper.cxx b/comphelper/source/misc/serviceinfohelper.cxx new file mode 100644 index 000000000000..90f62ba8deab --- /dev/null +++ b/comphelper/source/misc/serviceinfohelper.cxx @@ -0,0 +1,114 @@ +/* -*- 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 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unoprov.cxx,v $ + * $Revision: 1.72.92.1 $ + * + * 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_comphelper.hxx" + +#include "comphelper/serviceinfohelper.hxx" +#include <stdarg.h> + +// ##################################################################### + +namespace comphelper +{ + +/** returns an empty UString(). most times sufficient */ +::rtl::OUString SAL_CALL ServiceInfoHelper::getImplementationName() throw( ::com::sun::star::uno::RuntimeException ) +{ + return ::rtl::OUString(); +} + +/** the base implementation iterates over the service names from <code>getSupportedServiceNames</code> */ +sal_Bool SAL_CALL ServiceInfoHelper::supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException) +{ + return supportsService( ServiceName, getSupportedServiceNames() ); +} + +sal_Bool SAL_CALL ServiceInfoHelper::supportsService( const ::rtl::OUString& ServiceName, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& SupportedServices ) throw() +{ + const ::rtl::OUString * pArray = SupportedServices.getConstArray(); + for( sal_Int32 i = 0; i < SupportedServices.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +/** the base implementation has no supported services */ +::com::sun::star::uno::Sequence< ::rtl::OUString > ServiceInfoHelper::getSupportedServiceNames(void) throw( ::com::sun::star::uno::RuntimeException ) +{ + ::com::sun::star::uno::Sequence< ::rtl::OUString> aSeq(0); + return aSeq; +} + +/** this method concatenates the given sequences and returns the result + */ +::com::sun::star::uno::Sequence< ::rtl::OUString > ServiceInfoHelper::concatSequences( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rSeq1, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rSeq2 ) throw() +{ + const sal_Int32 nLen1 = rSeq1.getLength(); + const sal_Int32 nLen2 = rSeq2.getLength(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > aSeq( nLen1 + nLen2 ); + + ::rtl::OUString* pStrings = aSeq.getArray(); + + sal_Int32 nIdx; + const ::rtl::OUString* pStringSrc = rSeq1.getConstArray(); + for( nIdx = 0; nIdx < nLen1; nIdx++ ) + *pStrings++ = *pStringSrc++; + + pStringSrc = rSeq2.getConstArray(); + for( nIdx = 0; nIdx < nLen2; nIdx++ ) + *pStrings++ = *pStringSrc++; + + return aSeq; +} + +/** this method adds a variable number of char pointer to a given Sequence + */ +void ServiceInfoHelper::addToSequence( ::com::sun::star::uno::Sequence< ::rtl::OUString >& rSeq, sal_uInt16 nServices, /* char * */ ... ) throw() +{ + sal_uInt32 nCount = rSeq.getLength(); + + rSeq.realloc( nCount + nServices ); + rtl::OUString* pStrings = rSeq.getArray(); + + va_list marker; + va_start( marker, nServices ); + for( sal_uInt16 i = 0 ; i < nServices; i++ ) + pStrings[nCount++] = rtl::OUString::createFromAscii(va_arg( marker, char*)); + va_end( marker ); +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/sharedmutex.cxx b/comphelper/source/misc/sharedmutex.cxx new file mode 100644 index 000000000000..ab7d68be12d3 --- /dev/null +++ b/comphelper/source/misc/sharedmutex.cxx @@ -0,0 +1,65 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/sharedmutex.hxx" + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + //======================================================================== + //= SharedMutex + //======================================================================== + //------------------------------------------------------------------------ + SharedMutex::SharedMutex() + :m_pMutexImpl( new ::osl::Mutex ) + { + } + + //------------------------------------------------------------------------ + SharedMutex::SharedMutex( const SharedMutex& _rhs ) + :m_pMutexImpl() + { + *this = _rhs; + } + + //------------------------------------------------------------------------ + SharedMutex& SharedMutex::operator=( const SharedMutex& _rhs ) + { + m_pMutexImpl = _rhs.m_pMutexImpl; + return *this; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/stillreadwriteinteraction.cxx b/comphelper/source/misc/stillreadwriteinteraction.cxx new file mode 100644 index 000000000000..4ae3422fe869 --- /dev/null +++ b/comphelper/source/misc/stillreadwriteinteraction.cxx @@ -0,0 +1,141 @@ +/* -*- 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 +* <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_comphelper.hxx" +#include <comphelper/stillreadwriteinteraction.hxx> + +#include <com/sun/star/ucb/InteractiveIOException.hpp> + +#include <com/sun/star/task/XInteractionAbort.hpp> + +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> + +namespace comphelper{ + + namespace css = ::com::sun::star; + +StillReadWriteInteraction::StillReadWriteInteraction(const css::uno::Reference< css::task::XInteractionHandler >& xHandler) + : m_bUsed (sal_False) + , m_bHandledByMySelf (sal_False) + , m_bHandledByInternalHandler(sal_False) +{ + ::std::vector< ::ucbhelper::InterceptedInteraction::InterceptedRequest > lInterceptions; + ::ucbhelper::InterceptedInteraction::InterceptedRequest aInterceptedRequest; + + aInterceptedRequest.Handle = HANDLE_INTERACTIVEIOEXCEPTION; + aInterceptedRequest.Request <<= css::ucb::InteractiveIOException(); + aInterceptedRequest.Continuation = ::getCppuType(static_cast< css::uno::Reference< css::task::XInteractionAbort >* >(0)); + aInterceptedRequest.MatchExact = sal_False; + lInterceptions.push_back(aInterceptedRequest); + + aInterceptedRequest.Handle = HANDLE_UNSUPPORTEDDATASINKEXCEPTION; + aInterceptedRequest.Request <<= css::ucb::UnsupportedDataSinkException(); + aInterceptedRequest.Continuation = ::getCppuType(static_cast< css::uno::Reference< css::task::XInteractionAbort >* >(0)); + aInterceptedRequest.MatchExact = sal_False; + lInterceptions.push_back(aInterceptedRequest); + + setInterceptedHandler(xHandler); + setInterceptions(lInterceptions); +} + +void StillReadWriteInteraction::resetInterceptions() +{ + setInterceptions(::std::vector< ::ucbhelper::InterceptedInteraction::InterceptedRequest >()); +} + +void StillReadWriteInteraction::resetErrorStates() +{ + m_bUsed = sal_False; + m_bHandledByMySelf = sal_False; + m_bHandledByInternalHandler = sal_False; +} + +sal_Bool StillReadWriteInteraction::wasWriteError() +{ + return (m_bUsed && m_bHandledByMySelf); +} + +ucbhelper::InterceptedInteraction::EInterceptionState StillReadWriteInteraction::intercepted(const ::ucbhelper::InterceptedInteraction::InterceptedRequest& aRequest, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest >& xRequest) +{ + // we are used! + m_bUsed = sal_True; + + // check if its a real interception - might some parameters are not the right ones ... + sal_Bool bAbort = sal_False; + switch(aRequest.Handle) + { + case HANDLE_INTERACTIVEIOEXCEPTION: + { + css::ucb::InteractiveIOException exIO; + xRequest->getRequest() >>= exIO; + bAbort = ( + (exIO.Code == css::ucb::IOErrorCode_ACCESS_DENIED ) + || (exIO.Code == css::ucb::IOErrorCode_LOCKING_VIOLATION ) + || (exIO.Code == css::ucb::IOErrorCode_NOT_EXISTING ) +#ifdef MACOSX + // this is a workaround for MAC, on this platform if the file is locked + // the returned error code looks to be wrong + || (exIO.Code == css::ucb::IOErrorCode_GENERAL ) +#endif + ); + } + break; + + case HANDLE_UNSUPPORTEDDATASINKEXCEPTION: + { + bAbort = sal_True; + } + break; + } + + // handle interaction by ourself + if (bAbort) + { + m_bHandledByMySelf = sal_True; + css::uno::Reference< css::task::XInteractionContinuation > xAbort = ::ucbhelper::InterceptedInteraction::extractContinuation( + xRequest->getContinuations(), + ::getCppuType(static_cast< css::uno::Reference< css::task::XInteractionAbort >* >(0))); + if (!xAbort.is()) + return ::ucbhelper::InterceptedInteraction::E_NO_CONTINUATION_FOUND; + xAbort->select(); + return ::ucbhelper::InterceptedInteraction::E_INTERCEPTED; + } + + // Otherwhise use internal handler. + if (m_xInterceptedHandler.is()) + { + m_bHandledByInternalHandler = sal_True; + m_xInterceptedHandler->handle(xRequest); + } + return ::ucbhelper::InterceptedInteraction::E_INTERCEPTED; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx new file mode 100644 index 000000000000..98258b8f615e --- /dev/null +++ b/comphelper/source/misc/storagehelper.cxx @@ -0,0 +1,489 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XEncryptionProtectedSource.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/IllegalTypeException.hpp> + +#include <ucbhelper/content.hxx> + +#include <comphelper/fileformat.h> +#include <comphelper/processfactory.hxx> +#include <comphelper/documentconstants.hxx> + +#include <comphelper/storagehelper.hxx> + + +using namespace ::com::sun::star; + +namespace comphelper { + +// ---------------------------------------------------------------------- +uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetStorageFactory( + const uno::Reference< lang::XMultiServiceFactory >& xSF ) + throw ( uno::Exception ) +{ + uno::Reference< lang::XMultiServiceFactory > xFactory = xSF.is() ? xSF : ::comphelper::getProcessServiceFactory(); + if ( !xFactory.is() ) + throw uno::RuntimeException(); + + uno::Reference < lang::XSingleServiceFactory > xStorageFactory( + xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ), + uno::UNO_QUERY ); + + if ( !xStorageFactory.is() ) + throw uno::RuntimeException(); + + return xStorageFactory; +} + +// ---------------------------------------------------------------------- +uno::Reference< lang::XSingleServiceFactory > OStorageHelper::GetFileSystemStorageFactory( + const uno::Reference< lang::XMultiServiceFactory >& xSF ) + throw ( uno::Exception ) +{ + uno::Reference< lang::XMultiServiceFactory > xFactory = xSF.is() ? xSF : ::comphelper::getProcessServiceFactory(); + if ( !xFactory.is() ) + throw uno::RuntimeException(); + + uno::Reference < lang::XSingleServiceFactory > xStorageFactory( + xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.embed.FileSystemStorageFactory" ) ), + uno::UNO_QUERY ); + + if ( !xStorageFactory.is() ) + throw uno::RuntimeException(); + + return xStorageFactory; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetTemporaryStorage( + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( uno::Exception ) +{ + uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstance(), + uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL( + const ::rtl::OUString& aURL, + sal_Int32 nStorageMode, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( uno::Exception ) +{ + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= aURL; + aArgs[1] <<= nStorageMode; + + uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ), + uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2( + const ::rtl::OUString& aURL, + sal_Int32 nStorageMode, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( uno::Exception ) +{ + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= aURL; + aArgs[1] <<= nStorageMode; + + uno::Reference< lang::XSingleServiceFactory > xFact; + try { + ::ucbhelper::Content aCntnt( aURL, + uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + if (aCntnt.isDocument()) { + xFact = GetStorageFactory( xFactory ); + } else { + xFact = GetFileSystemStorageFactory( xFactory ); + } + } catch (uno::Exception &) { } + + if (!xFact.is()) throw uno::RuntimeException(); + + uno::Reference< embed::XStorage > xTempStorage( + xFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromInputStream( + const uno::Reference < io::XInputStream >& xStream, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( uno::Exception ) +{ + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xStream; + aArgs[1] <<= embed::ElementModes::READ; + + uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ), + uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromStream( + const uno::Reference < io::XStream >& xStream, + sal_Int32 nStorageMode, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( uno::Exception ) +{ + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xStream; + aArgs[1] <<= nStorageMode; + + uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ), + uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +void OStorageHelper::CopyInputToOutput( + const uno::Reference< io::XInputStream >& xInput, + const uno::Reference< io::XOutputStream >& xOutput ) + throw ( uno::Exception ) +{ + static const sal_Int32 nConstBufferSize = 32000; + + sal_Int32 nRead; + uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); + + do + { + nRead = xInput->readBytes ( aSequence, nConstBufferSize ); + if ( nRead < nConstBufferSize ) + { + uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead ); + xOutput->writeBytes ( aTempBuf ); + } + else + xOutput->writeBytes ( aSequence ); + } + while ( nRead == nConstBufferSize ); +} + +// ---------------------------------------------------------------------- +uno::Reference< io::XInputStream > OStorageHelper::GetInputStreamFromURL( + const ::rtl::OUString& aURL, + const uno::Reference< lang::XMultiServiceFactory >& xSF ) + throw ( uno::Exception ) +{ + uno::Reference< lang::XMultiServiceFactory > xFactory = xSF.is() ? xSF : ::comphelper::getProcessServiceFactory(); + if ( !xFactory.is() ) + throw uno::RuntimeException(); + + uno::Reference < ::com::sun::star::ucb::XSimpleFileAccess > xTempAccess( + xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), + uno::UNO_QUERY ); + + if ( !xTempAccess.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XInputStream > xInputStream = xTempAccess->openFileRead( aURL ); + if ( !xInputStream.is() ) + throw uno::RuntimeException(); + + return xInputStream; +} + +// ---------------------------------------------------------------------- +void OStorageHelper::SetCommonStoragePassword( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& aPass ) + throw ( uno::Exception ) +{ + uno::Reference< embed::XEncryptionProtectedSource > xEncrSet( xStorage, uno::UNO_QUERY ); + if ( !xEncrSet.is() ) + throw io::IOException(); // TODO + + xEncrSet->setEncryptionPassword( aPass ); +} + +// ---------------------------------------------------------------------- +sal_Int32 OStorageHelper::GetXStorageFormat( + const uno::Reference< embed::XStorage >& xStorage ) + throw ( uno::Exception ) +{ + uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW ); + + ::rtl::OUString aMediaType; + xStorProps->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ) >>= aMediaType; + + sal_Int32 nResult = 0; + + // TODO/LATER: the filter configuration could be used to detect it later, or batter a special service + if ( + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_WRITER_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_WRITER_WEB_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_DRAW_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_IMPRESS_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_CALC_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_CHART_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_VND_SUN_XML_MATH_ASCII ) + ) + { + nResult = SOFFICE_FILEFORMAT_60; + } + else + if ( + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII ) || + aMediaType.equalsIgnoreAsciiCaseAscii(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII ) + ) + { + nResult = SOFFICE_FILEFORMAT_8; + } + else + { + // the mediatype is not known + throw beans::IllegalTypeException(); + } + + return nResult; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetTemporaryStorageOfFormat( + const ::rtl::OUString& aFormat, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( uno::Exception ) +{ + uno::Reference< lang::XMultiServiceFactory > xFactoryToUse = xFactory.is() ? xFactory : ::comphelper::getProcessServiceFactory(); + if ( !xFactoryToUse.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XStream > xTmpStream( + xFactoryToUse->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ), + uno::UNO_QUERY_THROW ); + + return GetStorageOfFormatFromStream( aFormat, xTmpStream, embed::ElementModes::READWRITE, xFactoryToUse ); +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromURL( + const ::rtl::OUString& aFormat, + const ::rtl::OUString& aURL, + sal_Int32 nStorageMode, + const uno::Reference< lang::XMultiServiceFactory >& xFactory, + sal_Bool bRepairStorage ) + throw ( uno::Exception ) +{ + uno::Sequence< beans::PropertyValue > aProps( 1 ); + aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) ); + aProps[0].Value <<= aFormat; + if ( bRepairStorage ) + { + aProps.realloc( 2 ); + aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RepairPackage" ) ); + aProps[1].Value <<= bRepairStorage; + } + + uno::Sequence< uno::Any > aArgs( 3 ); + aArgs[0] <<= aURL; + aArgs[1] <<= nStorageMode; + aArgs[2] <<= aProps; + + uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ), + uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStream( + const ::rtl::OUString& aFormat, + const uno::Reference < io::XInputStream >& xStream, + const uno::Reference< lang::XMultiServiceFactory >& xFactory, + sal_Bool bRepairStorage ) + throw ( uno::Exception ) +{ + uno::Sequence< beans::PropertyValue > aProps( 1 ); + aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) ); + aProps[0].Value <<= aFormat; + if ( bRepairStorage ) + { + aProps.realloc( 2 ); + aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RepairPackage" ) ); + aProps[1].Value <<= bRepairStorage; + } + + uno::Sequence< uno::Any > aArgs( 3 ); + aArgs[0] <<= xStream; + aArgs[1] <<= embed::ElementModes::READ; + aArgs[2] <<= aProps; + + uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ), + uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream( + const ::rtl::OUString& aFormat, + const uno::Reference < io::XStream >& xStream, + sal_Int32 nStorageMode, + const uno::Reference< lang::XMultiServiceFactory >& xFactory, + sal_Bool bRepairStorage ) + throw ( uno::Exception ) +{ + uno::Sequence< beans::PropertyValue > aProps( 1 ); + aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) ); + aProps[0].Value <<= aFormat; + if ( bRepairStorage ) + { + aProps.realloc( 2 ); + aProps[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RepairPackage" ) ); + aProps[1].Value <<= bRepairStorage; + } + + uno::Sequence< uno::Any > aArgs( 3 ); + aArgs[0] <<= xStream; + aArgs[1] <<= nStorageMode; + aArgs[2] <<= aProps; + + uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( xFactory )->createInstanceWithArguments( aArgs ), + uno::UNO_QUERY ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + return xTempStorage; +} + +// ---------------------------------------------------------------------- +sal_Bool OStorageHelper::IsValidZipEntryFileName( const ::rtl::OUString& aName, sal_Bool bSlashAllowed ) +{ + return IsValidZipEntryFileName( aName.getStr(), aName.getLength(), bSlashAllowed ); +} + +// ---------------------------------------------------------------------- +sal_Bool OStorageHelper::IsValidZipEntryFileName( + const sal_Unicode *pChar, sal_Int32 nLength, sal_Bool bSlashAllowed ) +{ + for ( sal_Int32 i = 0; i < nLength; i++ ) + { + switch ( pChar[i] ) + { + case '\\': + case '?': + case '<': + case '>': + case '\"': + case '|': + case ':': + return sal_False; + case '/': + if ( !bSlashAllowed ) + return sal_False; + break; + default: + if ( pChar[i] < 32 || (pChar[i] >= 0xD800 && pChar[i] <= 0xDFFF) ) + return sal_False; + } + } + return sal_True; +} + +// ---------------------------------------------------------------------- +sal_Bool OStorageHelper::PathHasSegment( const ::rtl::OUString& aPath, const ::rtl::OUString& aSegment ) +{ + sal_Bool bResult = sal_False; + const sal_Int32 nPathLen = aPath.getLength(); + const sal_Int32 nSegLen = aSegment.getLength(); + + if ( nSegLen && nPathLen >= nSegLen ) + { + ::rtl::OUString aEndSegment( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + aEndSegment += aSegment; + + ::rtl::OUString aInternalSegment( aEndSegment ); + aInternalSegment += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + + if ( aPath.indexOf( aInternalSegment ) >= 0 ) + bResult = sal_True; + + if ( !bResult && !aPath.compareTo( aSegment, nSegLen ) ) + { + if ( nPathLen == nSegLen || aPath.getStr()[nSegLen] == (sal_Unicode)'/' ) + bResult = sal_True; + } + + if ( !bResult && nPathLen > nSegLen && aPath.copy( nPathLen - nSegLen - 1, nSegLen + 1 ).equals( aEndSegment ) ) + bResult = sal_True; + } + + return bResult; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/string.cxx b/comphelper/source/misc/string.cxx new file mode 100644 index 000000000000..41b0dde2a582 --- /dev/null +++ b/comphelper/source/misc/string.cxx @@ -0,0 +1,128 @@ +/* -*- 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_comphelper.hxx" +#include "sal/config.h" + +#include <cstddef> +#include <string.h> +#include <vector> +#include <algorithm> + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/types.h> + +#include <comphelper/string.hxx> +#include <comphelper/stlunosequence.hxx> +#include <comphelper/stl_types.hxx> + + +namespace comphelper { namespace string { + +rtl::OUString searchAndReplaceAsciiL( + rtl::OUString const & source, char const * from, sal_Int32 fromLength, + rtl::OUString const & to, sal_Int32 beginAt, sal_Int32 * replacedAt) +{ + sal_Int32 n = source.indexOfAsciiL(from, fromLength, beginAt); + if (replacedAt != NULL) { + *replacedAt = n; + } + return n == -1 ? source : source.replaceAt(n, fromLength, to); +} + +::rtl::OUString searchAndReplaceAllAsciiWithAscii( + const ::rtl::OUString& _source, const sal_Char* _from, const sal_Char* _to, + const sal_Int32 _beginAt ) +{ + sal_Int32 fromLength = strlen( _from ); + sal_Int32 n = _source.indexOfAsciiL( _from, fromLength, _beginAt ); + if ( n == -1 ) + return _source; + + ::rtl::OUString dest( _source ); + ::rtl::OUString to( ::rtl::OUString::createFromAscii( _to ) ); + do + { + dest = dest.replaceAt( n, fromLength, to ); + n = dest.indexOfAsciiL( _from, fromLength, n + to.getLength() ); + } + while ( n != -1 ); + + return dest; +} + +::rtl::OUString& searchAndReplaceAsciiI( + ::rtl::OUString & _source, sal_Char const * _asciiPattern, ::rtl::OUString const & _replace, + sal_Int32 _beginAt, sal_Int32 * _replacedAt ) +{ + sal_Int32 fromLength = strlen( _asciiPattern ); + sal_Int32 n = _source.indexOfAsciiL( _asciiPattern, fromLength, _beginAt ); + if ( _replacedAt != NULL ) + *_replacedAt = n; + + if ( n != -1 ) + _source = _source.replaceAt( n, fromLength, _replace ); + + return _source; +} + +// convert between sequence of string and comma separated string + +::rtl::OUString convertCommaSeparated( + ::com::sun::star::uno::Sequence< ::rtl::OUString > const& i_rSeq) +{ + ::rtl::OUStringBuffer buf; + ::comphelper::intersperse( + ::comphelper::stl_begin(i_rSeq), ::comphelper::stl_end(i_rSeq), + ::comphelper::OUStringBufferAppender(buf), + ::rtl::OUString::createFromAscii(", ")); + return buf.makeStringAndClear(); +} + +::com::sun::star::uno::Sequence< ::rtl::OUString > + convertCommaSeparated( ::rtl::OUString const& i_rString ) +{ + std::vector< ::rtl::OUString > vec; + sal_Int32 idx = 0; + do { + ::rtl::OUString kw = + i_rString.getToken(0, static_cast<sal_Unicode> (','), idx); + kw = kw.trim(); + if (kw.getLength() > 0) { + vec.push_back(kw); + } + } while (idx >= 0); + ::com::sun::star::uno::Sequence< ::rtl::OUString > kws(vec.size()); + std::copy(vec.begin(), vec.end(), stl_begin(kws)); + return kws; +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/synchronousdispatch.cxx b/comphelper/source/misc/synchronousdispatch.cxx new file mode 100644 index 000000000000..ca6362a6754b --- /dev/null +++ b/comphelper/source/misc/synchronousdispatch.cxx @@ -0,0 +1,104 @@ +/* -*- 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 + * <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_comphelper.hxx" + +/** === begin UNO includes === **/ +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/frame/XSynchronousDispatch.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/util/XURLTransformer.hpp" +/** === end UNO includes === **/ + +#include "comphelper/synchronousdispatch.hxx" +#include "comphelper/processfactory.hxx" + +#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +//......................................................................... +namespace comphelper +{ +//......................................................................... + +using namespace ::com::sun::star; + +//==================================================================== +//= SynchronousDispatch +//==================================================================== + +uno::Reference< lang::XComponent > SynchronousDispatch::dispatch( + const uno::Reference< uno::XInterface > &xStartPoint, + const rtl::OUString &sURL, + const rtl::OUString &sTarget, + const sal_Int32 nFlags, + const uno::Sequence< beans::PropertyValue > &lArguments ) +{ + util::URL aURL; + aURL.Complete = sURL; + uno::Reference < util::XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( + UNISTRING("com.sun.star.util.URLTransformer" )), + uno::UNO_QUERY ); + if ( xTrans.is() ) + xTrans->parseStrict( aURL ); + + uno::Reference < frame::XDispatch > xDispatcher; + uno::Reference < frame::XDispatchProvider > xProvider( xStartPoint, uno::UNO_QUERY ); + + if ( xProvider.is() ) + xDispatcher = xProvider->queryDispatch( aURL, sTarget, nFlags ); + + uno::Reference < lang::XComponent > aComponent; + + if ( xDispatcher.is() ) + { + try + { + uno::Any aRet; + uno::Reference < frame::XSynchronousDispatch > xSyncDisp( xDispatcher, uno::UNO_QUERY_THROW ); + + aRet = xSyncDisp->dispatchWithReturnValue( aURL, lArguments ); + + aRet >>= aComponent; + } + catch ( uno::Exception& ) + { + rtl::OUString aMsg = UNISTRING( "SynchronousDispatch::dispatch() Error while dispatching! "); + OSL_ENSURE( sal_False, OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + + return aComponent; +} + +//......................................................................... +} // namespace comphelper +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/types.cxx b/comphelper/source/misc/types.cxx new file mode 100644 index 000000000000..9be20ac52296 --- /dev/null +++ b/comphelper/source/misc/types.cxx @@ -0,0 +1,479 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/types.hxx> +#include <comphelper/extract.hxx> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <osl/diagnose.h> +#include <typelib/typedescription.hxx> + +#include <memory.h> + + +//......................................................................... +namespace comphelper +{ +//......................................................................... + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; + +//------------------------------------------------------------------------- +sal_Bool operator ==(const DateTime& _rLeft, const DateTime& _rRight) +{ + return ( _rLeft.HundredthSeconds == _rRight.HundredthSeconds) && + ( _rLeft.Seconds == _rRight.Seconds) && + ( _rLeft.Minutes == _rRight.Minutes) && + ( _rLeft.Hours == _rRight.Hours) && + ( _rLeft.Day == _rRight.Day) && + ( _rLeft.Month == _rRight.Month) && + ( _rLeft.Year == _rRight.Year) ; +} + +//------------------------------------------------------------------------- +sal_Bool operator ==(const Date& _rLeft, const Date& _rRight) +{ + return ( _rLeft.Day == _rRight.Day) && + ( _rLeft.Month == _rRight.Month) && + ( _rLeft.Year == _rRight.Year) ; +} + +//------------------------------------------------------------------------- +sal_Bool operator ==(const Time& _rLeft, const Time& _rRight) +{ + return ( _rLeft.HundredthSeconds == _rRight.HundredthSeconds) && + ( _rLeft.Seconds == _rRight.Seconds) && + ( _rLeft.Minutes == _rRight.Minutes) && + ( _rLeft.Hours == _rRight.Hours) ; +} + +//------------------------------------------------------------------------------ +sal_Int32 getINT32(const Any& _rAny) +{ + sal_Int32 nReturn = 0; + OSL_VERIFY( _rAny >>= nReturn ); + return nReturn; +} + +//------------------------------------------------------------------------------ +sal_Int16 getINT16(const Any& _rAny) +{ + sal_Int16 nReturn = 0; + OSL_VERIFY( _rAny >>= nReturn ); + return nReturn; +} + +//------------------------------------------------------------------------------ +double getDouble(const Any& _rAny) +{ + double nReturn = 0.0; + OSL_VERIFY( _rAny >>= nReturn ); + return nReturn; +} + +//------------------------------------------------------------------------------ +float getFloat(const Any& _rAny) +{ + float nReturn = 0.0; + OSL_VERIFY( _rAny >>= nReturn ); + return nReturn; +} + +//------------------------------------------------------------------------------ +::rtl::OUString getString(const Any& _rAny) +{ + ::rtl::OUString nReturn; + OSL_VERIFY( _rAny >>= nReturn ); + return nReturn; +} + +//------------------------------------------------------------------------------ +sal_Bool getBOOL(const Any& _rAny) +{ + sal_Bool nReturn = sal_False; + if (_rAny.getValueType() == ::getCppuBooleanType()) + nReturn = *(sal_Bool*)_rAny.getValue(); + else + OSL_ENSURE(sal_False, "comphelper::getBOOL : invalid argument !"); + return nReturn; +} + +//------------------------------------------------------------------------------ +sal_Int32 getEnumAsINT32(const Any& _rAny) throw(IllegalArgumentException) +{ + sal_Int32 nReturn = 0; + if (! ::cppu::enum2int(nReturn,_rAny) ) + throw IllegalArgumentException(); + return nReturn; +} + +//------------------------------------------------------------------------------ +FontDescriptor getDefaultFont() +{ + FontDescriptor aReturn; + aReturn.Slant = FontSlant_DONTKNOW; + aReturn.Underline = FontUnderline::DONTKNOW; + aReturn.Strikeout = FontStrikeout::DONTKNOW; + return aReturn; +} + +//------------------------------------------------------------------------------ +sal_Bool isAssignableFrom(const Type& _rAssignable, const Type& _rFrom) +{ + // getthe type lib descriptions + typelib_TypeDescription* pAssignable = NULL; + _rAssignable.getDescription(&pAssignable); + + typelib_TypeDescription* pFrom = NULL; + _rFrom.getDescription(&pFrom); + + // and ask the type lib + return typelib_typedescription_isAssignableFrom(pAssignable, pFrom); +} + +//------------------------------------------------------------------ +template<class TYPE> +sal_Bool tryCompare(const void* _pData, const Any& _rValue, sal_Bool& _bIdentical, TYPE& _rOut) +{ + sal_Bool bSuccess = _rValue >>= _rOut; + _bIdentical = bSuccess && (_rOut == *reinterpret_cast<const TYPE*>(_pData)); + return bSuccess; +} + +//------------------------------------------------------------------ +sal_Bool tryCompare(const void* _pData, const Any& _rValue, sal_Bool& _bIdentical, sal_Unicode& _rOut) +{ + sal_Bool bSuccess = ( _rValue.getValueTypeClass() == TypeClass_CHAR ); + if ( bSuccess ) + _rOut = *static_cast< const sal_Unicode* >( _rValue.getValue() ); + _bIdentical = bSuccess && ( _rOut == *static_cast< const sal_Unicode* >( _pData ) ); + return bSuccess; +} + +//------------------------------------------------------------------ +sal_Bool compare_impl(const Type& _rType, const void* pData, const Any& _rValue) +{ + sal_Bool bRes = sal_True; + + if (_rType.getTypeClass() == TypeClass_ANY) + { + // beides AnyWerte + if (_rValue.getValueType().getTypeClass() == TypeClass_ANY) + bRes = compare_impl( + reinterpret_cast<const Any*>(pData)->getValueType(), + reinterpret_cast<const Any*>(pData)->getValue(), + *reinterpret_cast<const Any*>(_rValue.getValue())); + else + bRes = compare_impl( + reinterpret_cast<const Any*>(pData)->getValueType(), + reinterpret_cast<const Any*>(pData)->getValue(), + _rValue); + } + else if ( (_rType.getTypeClass() == TypeClass_VOID) + || (_rValue.getValueType().getTypeClass() == TypeClass_VOID) + ) + { + bRes = _rType.getTypeClass() == _rValue.getValueType().getTypeClass(); + } + else + { + sal_Bool bConversionSuccess = sal_False; + switch (_rType.getTypeClass()) + { + case TypeClass_VOID: + bConversionSuccess = sal_True; + bRes = _rValue.getValueType().getTypeClass() == TypeClass_VOID; + break; + case TypeClass_BOOLEAN: + { + sal_Bool aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_CHAR: + { + sal_Unicode aDummy(0); + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_STRING: + { + ::rtl::OUString aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_FLOAT: + { + float aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_DOUBLE: + { + double aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_BYTE: + { + sal_Int8 aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_SHORT: + { + sal_Int16 aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_ENUM: + { + sal_Int32 nAsInt32 = 0; + bConversionSuccess = ::cppu::enum2int(nAsInt32, _rValue); + bRes = bConversionSuccess && (nAsInt32== *reinterpret_cast<const sal_Int32*>(pData)); + break; + } + case TypeClass_LONG: + { + sal_Int32 aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_UNSIGNED_SHORT: + { + sal_uInt16 aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_UNSIGNED_LONG: + { + sal_uInt32 aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_INTERFACE: + { + InterfaceRef aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + case TypeClass_STRUCT: + if (isA(_rType, static_cast<FontDescriptor*>(NULL))) + { + FontDescriptor aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + bRes = *(FontDescriptor*)pData == aTemp; + } + else + bRes = sal_False; + break; + } + if (isA(_rType, static_cast<Date*>(NULL))) + { + Date aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + if (isA(_rType, static_cast<Time*>(NULL))) + { + Time aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + if (isA(_rType, static_cast<DateTime*>(NULL))) + { + DateTime aDummy; + bConversionSuccess = tryCompare(pData, _rValue, bRes, aDummy); + break; + } + break; + case TypeClass_SEQUENCE: + if (isA(_rType, static_cast< Sequence<sal_Int8>* >(NULL))) + { + Sequence<sal_Int8> aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + const Sequence<sal_Int8>& rLeftSeq = *reinterpret_cast<const Sequence<sal_Int8>*>(pData); + const Sequence<sal_Int8>& rRightSeq = aTemp; + bRes = rLeftSeq.getLength() == rRightSeq.getLength() && + memcmp(rLeftSeq.getConstArray(), rRightSeq.getConstArray(), rLeftSeq.getLength()) == 0; + } + } + else if (isA(_rType, static_cast< Sequence<sal_uInt8>* >(NULL))) + { + Sequence<sal_uInt8> aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + const Sequence<sal_uInt8>& rLeftSeq = *reinterpret_cast<const Sequence<sal_uInt8>*>(pData); + const Sequence<sal_uInt8>& rRightSeq = aTemp; + bRes = rLeftSeq.getLength() == rRightSeq.getLength() && + memcmp(rLeftSeq.getConstArray(), rRightSeq.getConstArray(), rLeftSeq.getLength()) == 0; + } + } + else if (isA(_rType, static_cast< Sequence<sal_Int16>* >(NULL))) + { + Sequence<sal_Int16> aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + const Sequence<sal_Int16>& rLeftSeq = *reinterpret_cast<const Sequence<sal_Int16>*>(pData); + const Sequence<sal_Int16>& rRightSeq = aTemp; + bRes = rLeftSeq.getLength() == rRightSeq.getLength() && + memcmp(rLeftSeq.getConstArray(), rRightSeq.getConstArray(), rLeftSeq.getLength()*sizeof(sal_Int16)) == 0; + } + } + else if (isA(_rType, static_cast< Sequence<sal_uInt16>* >(NULL))) + { + Sequence<sal_uInt16> aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + const Sequence<sal_uInt16>& rLeftSeq = *reinterpret_cast<const Sequence<sal_uInt16>*>(pData); + const Sequence<sal_uInt16>& rRightSeq = aTemp; + bRes = rLeftSeq.getLength() == rRightSeq.getLength() && + memcmp(rLeftSeq.getConstArray(), rRightSeq.getConstArray(), rLeftSeq.getLength()*sizeof(sal_uInt16)) == 0; + } + } + else if (isA(_rType, static_cast< Sequence<sal_Int32>* >(NULL))) + { + Sequence<sal_Int32> aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + const Sequence<sal_Int32>& rLeftSeq = *reinterpret_cast<const Sequence<sal_Int32>*>(pData); + const Sequence<sal_Int32>& rRightSeq = aTemp; + bRes = rLeftSeq.getLength() == rRightSeq.getLength() && + memcmp(rLeftSeq.getConstArray(), rRightSeq.getConstArray(), rLeftSeq.getLength()*sizeof(sal_Int32)) == 0; + } + } + else if (isA(_rType, static_cast< Sequence<sal_uInt32>* >(NULL))) + { + Sequence<sal_uInt32> aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + const Sequence<sal_uInt32>& rLeftSeq = *reinterpret_cast<const Sequence<sal_uInt32>*>(pData); + const Sequence<sal_uInt32>& rRightSeq = aTemp; + bRes = rLeftSeq.getLength() == rRightSeq.getLength() && + memcmp(rLeftSeq.getConstArray(), rRightSeq.getConstArray(), rLeftSeq.getLength()*sizeof(sal_uInt32)) == 0; + } + } + else if (isA(_rType, static_cast< Sequence< ::rtl::OUString >* >(NULL))) + { + Sequence< ::rtl::OUString > aTemp; + bConversionSuccess = _rValue >>= aTemp; + if (bConversionSuccess) + { + const Sequence< ::rtl::OUString >& rLeftSeq = *reinterpret_cast<const Sequence< ::rtl::OUString>*>(pData); + const Sequence< ::rtl::OUString >& rRightSeq = aTemp; + sal_Int32 nSeqLen = rLeftSeq.getLength(); + bRes = ( nSeqLen == rRightSeq.getLength() ); + for ( sal_Int32 n = 0; bRes && ( n < nSeqLen ); n++ ) + { + const ::rtl::OUString& rS1 = rLeftSeq.getConstArray()[n]; + const ::rtl::OUString& rS2 = rRightSeq.getConstArray()[n]; + bRes = ( rS1 == rS2 ); + } + } + } + break; + default: + bRes = sal_False; + } + + bRes = bRes && bConversionSuccess; + } + return bRes; +} + +//------------------------------------------------------------------------------ +sal_Bool compare(const Any& rLeft, const Any& rRight) +{ + return compare_impl(rLeft.getValueType(), rLeft.getValue(), rRight); +} + +//------------------------------------------------------------------------- +sal_Bool operator ==(const FontDescriptor& _rLeft, const FontDescriptor& _rRight) +{ + return ( _rLeft.Name.equals( _rRight.Name ) ) && + ( _rLeft.Height == _rRight.Height ) && + ( _rLeft.Width == _rRight.Width ) && + ( _rLeft.StyleName.equals( _rRight.StyleName ) ) && + ( _rLeft.Family == _rRight.Family ) && + ( _rLeft.CharSet == _rRight.CharSet ) && + ( _rLeft.Pitch == _rRight.Pitch ) && + ( _rLeft.CharacterWidth == _rRight.CharacterWidth ) && + ( _rLeft.Weight == _rRight.Weight ) && + ( _rLeft.Slant == _rRight.Slant ) && + ( _rLeft.Underline == _rRight.Underline ) && + ( _rLeft.Strikeout == _rRight.Strikeout ) && + ( _rLeft.Orientation == _rRight.Orientation ) && + ( _rLeft.Kerning == _rRight.Kerning ) && + ( _rLeft.WordLineMode == _rRight.WordLineMode ) && + ( _rLeft.Type == _rRight.Type ) ; +} + +//------------------------------------------------------------------------- +Type getSequenceElementType(const Type& _rSequenceType) +{ + OSL_ENSURE(_rSequenceType.getTypeClass() == TypeClass_SEQUENCE, + "getSequenceElementType: must be called with a sequence type!"); + + if (!(_rSequenceType.getTypeClass() == TypeClass_SEQUENCE)) + return Type(); + + TypeDescription aTD(_rSequenceType); + typelib_IndirectTypeDescription* pSequenceTD = + reinterpret_cast< typelib_IndirectTypeDescription* >(aTD.get()); + + OSL_ASSERT(pSequenceTD); + OSL_ASSERT(pSequenceTD->pType); + + if (pSequenceTD && pSequenceTD->pType) + return Type(pSequenceTD->pType); + + return Type(); +} +//......................................................................... +} // namespace comphelper +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/uieventslogger.cxx b/comphelper/source/misc/uieventslogger.cxx new file mode 100644 index 000000000000..6c5a147bb0fb --- /dev/null +++ b/comphelper/source/misc/uieventslogger.cxx @@ -0,0 +1,689 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include <comphelper/uieventslogger.hxx> +#include <boost/shared_ptr.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/logging/LogLevel.hpp> +#include <com/sun/star/logging/XCsvLogFormatter.hpp> +#include <com/sun/star/logging/XLogHandler.hpp> +#include <com/sun/star/logging/XLogger.hpp> +#include <com/sun/star/logging/XLoggerPool.hpp> +#include <com/sun/star/oooimprovement/XCoreController.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/util/XStringSubstitution.hpp> +#include <comphelper/configurationhelper.hxx> +#include <comphelper/processfactory.hxx> +#include <map> +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#include <osl/time.h> +#include <rtl/ustrbuf.hxx> + + +using namespace com::sun::star::beans; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::logging; +using namespace com::sun::star::oooimprovement; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace cppu; +using namespace osl; +using namespace rtl; +using namespace std; + + +namespace +{ + static void lcl_SetupOriginAppAbbr(map<OUString, OUString>& abbrs) + { + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextDocument"))] = OUString(sal_Unicode('W')); // Writer + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetDocument"))] = OUString(sal_Unicode('C')); // Calc + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationDocument"))] = OUString(sal_Unicode('I')); // Impress + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocument"))] = OUString(sal_Unicode('D')); // Draw + }; + + static void lcl_SetupOriginWidgetAbbr(map<OUString,OUString>& abbrs) + { + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("ButtonToolbarController"))] = OUString(sal_Unicode('0')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("ComplexToolbarController"))] = OUString(sal_Unicode('1')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("ControlMenuController"))] = OUString(sal_Unicode('2')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("FontMenuController"))] = OUString(sal_Unicode('3')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("FontSizeMenuController"))] = OUString(sal_Unicode('4')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("FooterMenuController"))] = OUString(sal_Unicode('5')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("GenericToolbarController"))] = OUString(sal_Unicode('6')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("HeaderMenuController"))] = OUString(sal_Unicode('7')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("LanguageSelectionMenuController"))] = OUString(sal_Unicode('8')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("LangSelectionStatusbarController"))] = OUString(sal_Unicode('9')); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("MacrosMenuController"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("10")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("MenuBarManager"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("11")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("NewMenuController"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("12")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("ObjectMenuController"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("13")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("RecentFilesMenuController"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("14")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("ToolbarsMenuController"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("15")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("SfxToolBoxControl"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("16")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("SfxAsyncExec"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("17")); + abbrs[OUString(RTL_CONSTASCII_USTRINGPARAM("AcceleratorExecute"))] = OUString(RTL_CONSTASCII_USTRINGPARAM("18")); + }; +} + +namespace comphelper +{ + // declaration of implementation + class UiEventsLogger_Impl; + class UiEventsLogger_Impl : public UiEventsLogger + { + private: + //typedefs and friends + friend class UiEventsLogger; + typedef UiEventsLogger_Impl* ptr; + + // instance methods and data + UiEventsLogger_Impl(); + void initializeLogger(); + void logDispatch(const ::com::sun::star::util::URL& url, + const Sequence<PropertyValue>& args); + void logRotated(); + void logVcl(const ::rtl::OUString& parent_id, + sal_Int32 window_type, + const ::rtl::OUString& id, + const ::rtl::OUString& method, + const ::rtl::OUString& param); + void rotate(); + void hotRotate(); + void prepareLogHandler(); + void checkIdleTimeout(); + OUString getCurrentPath(); + OUString getRotatedPath(); + void disposing(); + + bool m_Active; + TimeValue m_LastLogEventTime; + const OUString m_LogPath; + const TimeValue m_IdleTimeout; + sal_Int32 m_SessionLogEventCount; + Reference<XLogger> m_Logger; + Reference<XLogHandler> m_LogHandler; + Reference<XCsvLogFormatter> m_Formatter; + map<OUString, OUString> m_OriginAppAbbr; + map<OUString, OUString> m_OriginWidgetAbbr; + + + // static methods and data + static ptr getInstance(); + static void prepareMutex(); + static bool shouldActivate(); + static bool getEnabledFromCoreController(); + static bool getEnabledFromCfg(); + static TimeValue getIdleTimeoutFromCfg(); + static OUString getLogPathFromCfg(); + static sal_Int32 findIdx(const Sequence<PropertyValue>& args, const OUString& key); + + static ptr instance; + static Mutex * singleton_mutex; + static const sal_Int32 COLUMNS; + static const OUString CFG_ENABLED; + static const OUString CFG_IDLETIMEOUT; + static const OUString CFG_LOGGING; + static const OUString CFG_LOGPATH; + static const OUString CFG_OOOIMPROVEMENT; + static const OUString ETYPE_DISPATCH; + static const OUString ETYPE_ROTATED; + static const OUString ETYPE_VCL; + static const OUString CSSL_CSVFORMATTER; + static const OUString CSSL_FILEHANDLER; + static const OUString CSSL_LOGGERPOOL; + static const OUString CSSO_CORECONTROLLER; + static const OUString CSST_JOBEXECUTOR; + static const OUString CSSU_PATHSUB; + static const OUString LOGGERNAME; + static const OUString LOGORIGINAPP; + static const OUString LOGORIGINWIDGET; + static const OUString UNKNOWN_ORIGIN; + static const OUString FN_CURRENTLOG; + static const OUString FN_ROTATEDLOG; + static const OUString LOGROTATE_EVENTNAME; + static const OUString URL_UNO; + static const OUString URL_FILE; + }; +} + +namespace comphelper +{ + // consts + const sal_Int32 UiEventsLogger_Impl::COLUMNS = 9; + const OUString UiEventsLogger_Impl::CFG_ENABLED(RTL_CONSTASCII_USTRINGPARAM("EnablingAllowed")); + const OUString UiEventsLogger_Impl::CFG_IDLETIMEOUT(RTL_CONSTASCII_USTRINGPARAM("IdleTimeout")); + const OUString UiEventsLogger_Impl::CFG_LOGGING(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Logging")); + const OUString UiEventsLogger_Impl::CFG_LOGPATH(RTL_CONSTASCII_USTRINGPARAM("LogPath")); + const OUString UiEventsLogger_Impl::CFG_OOOIMPROVEMENT(RTL_CONSTASCII_USTRINGPARAM("OOoImprovement")); + + const OUString UiEventsLogger_Impl::CSSL_CSVFORMATTER(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.logging.CsvFormatter")); + const OUString UiEventsLogger_Impl::CSSL_FILEHANDLER(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.logging.FileHandler")); + const OUString UiEventsLogger_Impl::CSSL_LOGGERPOOL(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.logging.LoggerPool")); + const OUString UiEventsLogger_Impl::CSSO_CORECONTROLLER(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.oooimprovement.CoreController")); + const OUString UiEventsLogger_Impl::CSSU_PATHSUB(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.PathSubstitution")); + + const OUString UiEventsLogger_Impl::ETYPE_DISPATCH(RTL_CONSTASCII_USTRINGPARAM("dispatch")); + const OUString UiEventsLogger_Impl::ETYPE_ROTATED(RTL_CONSTASCII_USTRINGPARAM("rotated")); + const OUString UiEventsLogger_Impl::ETYPE_VCL(RTL_CONSTASCII_USTRINGPARAM("vcl")); + + const OUString UiEventsLogger_Impl::LOGGERNAME(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.oooimprovement.Core.UiEventsLogger")); + const OUString UiEventsLogger_Impl::LOGORIGINWIDGET(RTL_CONSTASCII_USTRINGPARAM("comphelper.UiEventsLogger.LogOriginWidget")); + const OUString UiEventsLogger_Impl::LOGORIGINAPP(RTL_CONSTASCII_USTRINGPARAM("comphelper.UiEventsLogger.LogOriginApp")); + + const OUString UiEventsLogger_Impl::UNKNOWN_ORIGIN(RTL_CONSTASCII_USTRINGPARAM("unknown origin")); + const OUString UiEventsLogger_Impl::FN_CURRENTLOG(RTL_CONSTASCII_USTRINGPARAM("Current")); + const OUString UiEventsLogger_Impl::FN_ROTATEDLOG(RTL_CONSTASCII_USTRINGPARAM("OOoImprove")); + const OUString UiEventsLogger_Impl::LOGROTATE_EVENTNAME(RTL_CONSTASCII_USTRINGPARAM("onOOoImprovementLogRotated")); + + const OUString UiEventsLogger_Impl::URL_UNO(RTL_CONSTASCII_USTRINGPARAM(".uno:")); + const OUString UiEventsLogger_Impl::URL_FILE(RTL_CONSTASCII_USTRINGPARAM("file:")); + + + // public UiEventsLogger interface + sal_Bool UiEventsLogger::isEnabled() + { + if ( UiEventsLogger_Impl::getEnabledFromCfg() ) + { + try { + UiEventsLogger_Impl::prepareMutex(); + Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); + return UiEventsLogger_Impl::getInstance()->m_Active; + } catch(...) { return false; } // never throws + } // if ( ) + return sal_False; + } + + sal_Int32 UiEventsLogger::getSessionLogEventCount() + { + try { + UiEventsLogger_Impl::prepareMutex(); + Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); + return UiEventsLogger_Impl::getInstance()->m_SessionLogEventCount; + } catch(...) { return 0; } // never throws + } + + void UiEventsLogger::appendDispatchOrigin( + Sequence<PropertyValue>& args, + const OUString& originapp, + const OUString& originwidget) + { + sal_Int32 old_length = args.getLength(); + args.realloc(old_length+2); + args[old_length].Name = UiEventsLogger_Impl::LOGORIGINAPP; + args[old_length].Value = static_cast<Any>(originapp); + args[old_length+1].Name = UiEventsLogger_Impl::LOGORIGINWIDGET; + args[old_length+1].Value = static_cast<Any>(originwidget); + } + + Sequence<PropertyValue> UiEventsLogger::purgeDispatchOrigin( + const Sequence<PropertyValue>& args) + { + Sequence<PropertyValue> result(args.getLength()); + sal_Int32 target_idx=0; + for(sal_Int32 source_idx=0; source_idx<args.getLength(); source_idx++) + if(args[source_idx].Name != UiEventsLogger_Impl::LOGORIGINAPP + && args[source_idx].Name != UiEventsLogger_Impl::LOGORIGINWIDGET) + result[target_idx++] = args[source_idx]; + result.realloc(target_idx); + return result; + } + + void UiEventsLogger::logDispatch( + const URL& url, + const Sequence<PropertyValue>& args) + { + try { + UiEventsLogger_Impl::prepareMutex(); + Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); + UiEventsLogger_Impl::getInstance()->logDispatch(url, args); + } catch(...) { } // never throws + } + + void UiEventsLogger::logVcl( + const OUString& parent_id, + sal_Int32 window_type, + const OUString& id, + const OUString& method, + const OUString& param) + { + try { + UiEventsLogger_Impl::prepareMutex(); + Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); + UiEventsLogger_Impl::getInstance()->logVcl(parent_id, window_type, id, method, param); + } catch(...) { } // never throws + } + + void UiEventsLogger::logVcl( + const OUString& parent_id, + sal_Int32 window_type, + const OUString& id, + const OUString& method, + sal_Int32 param) + { + OUStringBuffer buf; + UiEventsLogger::logVcl(parent_id, window_type, id, method, buf.append(param).makeStringAndClear()); + } + + void UiEventsLogger::logVcl( + const OUString& parent_id, + sal_Int32 window_type, + const OUString& id, + const OUString& method) + { + OUString empty; + UiEventsLogger::logVcl(parent_id, window_type, id, method, empty); + } + + void UiEventsLogger::disposing() + { + // we dont want to create an instance just to dispose it + UiEventsLogger_Impl::prepareMutex(); + Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); + if(UiEventsLogger_Impl::instance!=UiEventsLogger_Impl::ptr()) + UiEventsLogger_Impl::getInstance()->disposing(); + } + + void UiEventsLogger::reinit() + { + UiEventsLogger_Impl::prepareMutex(); + Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); + if(UiEventsLogger_Impl::instance) + { + UiEventsLogger_Impl::instance->disposing(); + delete UiEventsLogger_Impl::instance; + UiEventsLogger_Impl::instance = NULL; + } + } + + // private UiEventsLogger_Impl methods + UiEventsLogger_Impl::UiEventsLogger_Impl() + : m_Active(UiEventsLogger_Impl::shouldActivate()) + , m_LogPath(UiEventsLogger_Impl::getLogPathFromCfg()) + , m_IdleTimeout(UiEventsLogger_Impl::getIdleTimeoutFromCfg()) + , m_SessionLogEventCount(0) + { + lcl_SetupOriginAppAbbr(m_OriginAppAbbr); + lcl_SetupOriginWidgetAbbr(m_OriginWidgetAbbr); + m_LastLogEventTime.Seconds = m_LastLogEventTime.Nanosec = 0; + if(m_Active) rotate(); + if(m_Active) initializeLogger(); + } + + void UiEventsLogger_Impl::logDispatch( + const URL& url, + const Sequence<PropertyValue>& args) + { + if(!m_Active) return; + if(!url.Complete.match(URL_UNO) && !url.Complete.match(URL_FILE)) return; + checkIdleTimeout(); + + Sequence<OUString> logdata = Sequence<OUString>(COLUMNS); + logdata[0] = ETYPE_DISPATCH; + sal_Int32 originapp_idx = findIdx(args, LOGORIGINAPP); + if(originapp_idx!=-1) + { + OUString app; + args[originapp_idx].Value >>= app; + map<OUString, OUString>::iterator abbr_it = m_OriginAppAbbr.find(app); + if(abbr_it != m_OriginAppAbbr.end()) + app = abbr_it->second; + logdata[1] = app; + } + else + logdata[1] = UNKNOWN_ORIGIN; + sal_Int32 originwidget_idx = findIdx(args, LOGORIGINWIDGET); + if(originwidget_idx!=-1) + { + OUString widget; + args[originwidget_idx].Value >>= widget; + map<OUString, OUString>::iterator widget_it = m_OriginWidgetAbbr.find(widget); + if(widget_it != m_OriginWidgetAbbr.end()) + widget = widget_it->second; + logdata[2] = widget; + } + else + logdata[2] = UNKNOWN_ORIGIN; + if(url.Complete.match(URL_FILE)) + logdata[3] = URL_FILE; + else + logdata[3] = url.Main; + OSL_TRACE("UiEventsLogger Logging: %s,%s,%s,%s,%s,%s,%s,%s", + OUStringToOString(logdata[0],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[1],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[2],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[3],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[4],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[5],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[6],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[7],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[8],RTL_TEXTENCODING_UTF8).getStr()); + m_Logger->log(LogLevel::INFO, m_Formatter->formatMultiColumn(logdata)); + m_SessionLogEventCount++; + } + + void UiEventsLogger_Impl::logRotated() + { + Sequence<OUString> logdata = Sequence<OUString>(COLUMNS); + logdata[0] = ETYPE_ROTATED; + OSL_TRACE("UiEventsLogger Logging: %s,%s,%s,%s,%s,%s,%s,%s", + OUStringToOString(logdata[0],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[1],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[2],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[3],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[4],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[5],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[6],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[7],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[8],RTL_TEXTENCODING_UTF8).getStr()); + m_Logger->log(LogLevel::INFO, m_Formatter->formatMultiColumn(logdata)); + } + + void UiEventsLogger_Impl::logVcl( + const OUString& parent_id, + sal_Int32 window_type, + const OUString& id, + const OUString& method, + const OUString& param) + { + if(!m_Active) return; + checkIdleTimeout(); + + OUStringBuffer buf; + Sequence<OUString> logdata = Sequence<OUString>(COLUMNS); + logdata[0] = ETYPE_VCL; + logdata[4] = parent_id; + logdata[5] = buf.append(window_type).makeStringAndClear(); + logdata[6] = id; + logdata[7] = method; + logdata[8] = param; + OSL_TRACE("UiEventsLogger Logging: %s,%s,%s,%s,%s,%s,%s,%s", + OUStringToOString(logdata[0],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[1],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[2],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[3],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[4],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[5],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[6],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[7],RTL_TEXTENCODING_UTF8).getStr(), + OUStringToOString(logdata[8],RTL_TEXTENCODING_UTF8).getStr()); + m_Logger->log(LogLevel::INFO, m_Formatter->formatMultiColumn(logdata)); + m_SessionLogEventCount++; + } + + void UiEventsLogger_Impl::rotate() + { + FileBase::RC result = File::move(getCurrentPath(), getRotatedPath()); + if(result!=FileBase::E_None && result!=FileBase::E_NOENT) + m_Active = false; + } + + void UiEventsLogger_Impl::hotRotate() + { + logRotated(); + m_Logger->removeLogHandler(m_LogHandler); + m_LogHandler = NULL; + rotate(); + prepareLogHandler(); + if(m_Formatter.is() && m_LogHandler.is() && m_Logger.is()) + { + m_LogHandler->setFormatter(Reference<XLogFormatter>(m_Formatter, UNO_QUERY)); + m_LogHandler->setLevel(LogLevel::ALL); + m_Logger->addLogHandler(m_LogHandler); + } + else + m_Active = false; + } + + void UiEventsLogger_Impl::prepareLogHandler() + { + Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); + + Sequence<Any> init_args = Sequence<Any>(1); + init_args[0] = static_cast<Any>(getCurrentPath()); + Reference< XInterface > temp = + sm->createInstanceWithArguments(CSSL_FILEHANDLER, init_args); + m_LogHandler = Reference<XLogHandler>(temp, UNO_QUERY); + } + + void UiEventsLogger_Impl::checkIdleTimeout() + { + TimeValue now; + osl_getSystemTime(&now); + if(now.Seconds - m_LastLogEventTime.Seconds > m_IdleTimeout.Seconds && m_SessionLogEventCount>0) + hotRotate(); + m_LastLogEventTime = now; + } + + OUString UiEventsLogger_Impl::getCurrentPath() + { + OUStringBuffer current_path(m_LogPath); + current_path.appendAscii("/"); + current_path.append(FN_CURRENTLOG); + current_path.appendAscii(".csv"); + return current_path.makeStringAndClear(); + } + + OUString UiEventsLogger_Impl::getRotatedPath() + { + OUStringBuffer rotated_path(m_LogPath); + rotated_path.appendAscii("/"); + rotated_path.append(FN_ROTATEDLOG); + rotated_path.appendAscii("-"); + { + // ISO 8601 + char tsrotated_pathfer[20]; + oslDateTime now; + TimeValue now_tv; + osl_getSystemTime(&now_tv); + osl_getDateTimeFromTimeValue(&now_tv, &now); + const size_t rotated_pathfer_size = sizeof(tsrotated_pathfer); + snprintf(tsrotated_pathfer, rotated_pathfer_size, "%04i-%02i-%02iT%02i_%02i_%02i", + now.Year, + now.Month, + now.Day, + now.Hours, + now.Minutes, + now.Seconds); + rotated_path.appendAscii(tsrotated_pathfer); + rotated_path.appendAscii(".csv"); + } + return rotated_path.makeStringAndClear(); + } + + void UiEventsLogger_Impl::initializeLogger() + { + Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); + + // getting the Core Uno proxy object + // It will call disposing and make sure we clear all our references + { + Reference<XTerminateListener> xCore( + sm->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.oooimprovement.Core"))), + UNO_QUERY); + Reference<XDesktop> xDesktop( + sm->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop"))), + UNO_QUERY); + if(!(xCore.is() && xDesktop.is())) + { + m_Active = false; + return; + } + xDesktop->addTerminateListener(xCore); + } + // getting the LoggerPool + Reference<XLoggerPool> pool; + { + Reference<XInterface> temp = + sm->createInstance(CSSL_LOGGERPOOL); + pool = Reference<XLoggerPool>(temp, UNO_QUERY); + } + + // getting the Logger + m_Logger = pool->getNamedLogger(LOGGERNAME); + + // getting the FileHandler + prepareLogHandler(); + + // getting the Formatter + { + Reference<XInterface> temp = + sm->createInstance(CSSL_CSVFORMATTER); + m_Formatter = Reference<XCsvLogFormatter>(temp, UNO_QUERY); + } + + if(m_Formatter.is() && m_LogHandler.is() && m_Logger.is()) + { + Sequence<OUString> columns = Sequence<OUString>(COLUMNS); + columns[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("eventtype")); + columns[1] = OUString(RTL_CONSTASCII_USTRINGPARAM("originapp")); + columns[2] = OUString(RTL_CONSTASCII_USTRINGPARAM("originwidget")); + columns[3] = OUString(RTL_CONSTASCII_USTRINGPARAM("uno url")); + columns[4] = OUString(RTL_CONSTASCII_USTRINGPARAM("parent id")); + columns[5] = OUString(RTL_CONSTASCII_USTRINGPARAM("window type")); + columns[6] = OUString(RTL_CONSTASCII_USTRINGPARAM("id")); + columns[7] = OUString(RTL_CONSTASCII_USTRINGPARAM("method")); + columns[8] = OUString(RTL_CONSTASCII_USTRINGPARAM("parameter")); + m_Formatter->setColumnnames(columns); + m_LogHandler->setFormatter(Reference<XLogFormatter>(m_Formatter, UNO_QUERY)); + m_Logger->setLevel(LogLevel::ALL); + m_LogHandler->setLevel(LogLevel::ALL); + m_Logger->addLogHandler(m_LogHandler); + } + else + m_Active = false; + } + + // private static UiEventsLogger_Impl + bool UiEventsLogger_Impl::shouldActivate() + { + return getEnabledFromCfg() && getEnabledFromCoreController(); + } + + OUString UiEventsLogger_Impl::getLogPathFromCfg() + { + OUString result; + Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); + + ConfigurationHelper::readDirectKey( + sm, + CFG_LOGGING, CFG_OOOIMPROVEMENT, CFG_LOGPATH, + ConfigurationHelper::E_READONLY + ) >>= result; + + Reference<XStringSubstitution> path_sub( + sm->createInstance(CSSU_PATHSUB), + UNO_QUERY); + if(path_sub.is()) + result = path_sub->substituteVariables(result, sal_False); + return result; + } + + TimeValue UiEventsLogger_Impl::getIdleTimeoutFromCfg() + { + sal_Int32 timeoutminutes = 360; + Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); + + ConfigurationHelper::readDirectKey( + sm, + CFG_LOGGING, CFG_OOOIMPROVEMENT, CFG_IDLETIMEOUT, + ConfigurationHelper::E_READONLY + ) >>= timeoutminutes; + TimeValue result; + result.Seconds = static_cast<sal_uInt32>(timeoutminutes)*60; + result.Nanosec = 0; + return result; + } + + bool UiEventsLogger_Impl::getEnabledFromCfg() + { + sal_Bool result = false; + Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); + ConfigurationHelper::readDirectKey( + sm, + CFG_LOGGING, CFG_OOOIMPROVEMENT, CFG_ENABLED, + ::comphelper::ConfigurationHelper::E_READONLY + ) >>= result; + return result; + } + + bool UiEventsLogger_Impl::getEnabledFromCoreController() + { + Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); + Reference<XCoreController> core_c( + sm->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.oooimprovement.CoreController"))), + UNO_QUERY); + if(!core_c.is()) return false; + return core_c->enablingUiEventsLoggerAllowed(1); + } + + UiEventsLogger_Impl::ptr UiEventsLogger_Impl::instance = UiEventsLogger_Impl::ptr(); + UiEventsLogger_Impl::ptr UiEventsLogger_Impl::getInstance() + { + if(instance == NULL) + instance = UiEventsLogger_Impl::ptr(new UiEventsLogger_Impl()); + return instance; + } + + Mutex * UiEventsLogger_Impl::singleton_mutex = NULL; + void UiEventsLogger_Impl::prepareMutex() + { + if(singleton_mutex == NULL) + { + Guard<Mutex> global_guard(Mutex::getGlobalMutex()); + if(singleton_mutex == NULL) + singleton_mutex = new Mutex(); + } + } + + sal_Int32 UiEventsLogger_Impl::findIdx(const Sequence<PropertyValue>& args, const OUString& key) + { + for(sal_Int32 i=0; i<args.getLength(); i++) + if(args[i].Name == key) + return i; + return -1; + } + + void UiEventsLogger_Impl::disposing() + { + m_Active = false; + m_Logger.clear() ; + m_LogHandler.clear(); + m_Formatter.clear(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/weak.cxx b/comphelper/source/misc/weak.cxx new file mode 100644 index 000000000000..51a7ef3be0c0 --- /dev/null +++ b/comphelper/source/misc/weak.cxx @@ -0,0 +1,78 @@ +/* -*- 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 + * <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_comphelper.hxx" + +#include "comphelper/weak.hxx" + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + +namespace comphelper +{ + +OWeakTypeObject::OWeakTypeObject() +{ +} + +OWeakTypeObject::~OWeakTypeObject() +{ +} + +Any SAL_CALL OWeakTypeObject::queryInterface(const Type & rType ) throw (RuntimeException) +{ + if( rType == XTypeProvider::static_type() ) + return Any( Reference< XTypeProvider >(this) ); + else + return ::cppu::OWeakObject::queryInterface( rType ); +} + +void SAL_CALL OWeakTypeObject::acquire() throw () +{ + ::cppu::OWeakObject::acquire(); +} + +void SAL_CALL OWeakTypeObject::release() throw () +{ + ::cppu::OWeakObject::release(); +} + +Sequence< Type > SAL_CALL OWeakTypeObject::getTypes( ) throw (RuntimeException) +{ + return Sequence< Type >(); +} + +Sequence< ::sal_Int8 > SAL_CALL OWeakTypeObject::getImplementationId( ) throw (RuntimeException) +{ + return Sequence< ::sal_Int8 >(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/weakeventlistener.cxx b/comphelper/source/misc/weakeventlistener.cxx new file mode 100644 index 000000000000..a02edf3d8881 --- /dev/null +++ b/comphelper/source/misc/weakeventlistener.cxx @@ -0,0 +1,95 @@ +/* -*- 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 + * <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_comphelper.hxx" +#include <comphelper/weakeventlistener.hxx> +#include <osl/diagnose.h> + + +//......................................................................... +namespace comphelper +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + + //===================================================================== + //= OWeakListenerAdapter + //===================================================================== + //--------------------------------------------------------------------- + OWeakListenerAdapterBase::~OWeakListenerAdapterBase() + { + } + + //===================================================================== + //= OWeakEventListenerAdapter + //===================================================================== + //--------------------------------------------------------------------- + OWeakEventListenerAdapter::OWeakEventListenerAdapter( Reference< XWeak > _rxListener, Reference< XComponent > _rxBroadcaster ) + :OWeakEventListenerAdapter_Base( _rxListener, _rxBroadcaster ) + { + // add ourself as listener to the broadcaster + OSL_ENSURE( _rxBroadcaster.is(), "OWeakEventListenerAdapter::OWeakEventListenerAdapter: invalid broadcaster!" ); + if ( _rxBroadcaster.is() ) + { + osl_incrementInterlockedCount( &m_refCount ); + { + _rxBroadcaster->addEventListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + OSL_ENSURE( m_refCount > 0, "OWeakEventListenerAdapter::OWeakEventListenerAdapter: oops - not to be used with implementations which hold their listeners weak!" ); + // the one and only reason for this adapter class (A) is to add as listener to a component (C) which + // holds its listeners hard, and forward all calls then to another listener (L) which is + // held weak by A. + // Now if C holds listeners weak, then we do not need A, we can add L directly to C. + } + + OSL_ENSURE( getListener().is(), "OWeakEventListenerAdapter::OWeakEventListenerAdapter: invalid listener (does not support the XEventListener interface)!" ); + } + + //--------------------------------------------------------------------- + void SAL_CALL OWeakEventListenerAdapter::disposing( ) + { + Reference< XComponent > xBroadcaster( getBroadcaster( ), UNO_QUERY ); + OSL_ENSURE( xBroadcaster.is(), "OWeakEventListenerAdapter::disposing: broadcaster is invalid in the meantime! How this?" ); + if ( xBroadcaster.is() ) + { + xBroadcaster->removeEventListener( this ); + } + + resetListener(); + } + +//......................................................................... +} // namespace comphelper +//......................................................................... + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |