diff options
Diffstat (limited to 'uui/source/iahndl.cxx')
-rw-r--r-- | uui/source/iahndl.cxx | 211 |
1 files changed, 148 insertions, 63 deletions
diff --git a/uui/source/iahndl.cxx b/uui/source/iahndl.cxx index b6c1eb613f5f..e883bd60848d 100644 --- a/uui/source/iahndl.cxx +++ b/uui/source/iahndl.cxx @@ -34,13 +34,11 @@ #include "com/sun/star/container/XHierarchicalNameAccess.hpp" #include "com/sun/star/document/BrokenPackageRequest.hpp" #include "com/sun/star/task/DocumentMacroConfirmationRequest.hpp" -#include "com/sun/star/task/DocumentMacroConfirmationRequest2.hpp" #include "com/sun/star/java/WrongJavaVersionException.hpp" #include "com/sun/star/lang/XInitialization.hpp" #include "com/sun/star/lang/XMultiServiceFactory.hpp" #include "com/sun/star/script/ModuleSizeExceededRequest.hpp" #include "com/sun/star/sync2/BadPartnershipException.hpp" -#include "com/sun/star/task/DocumentMacroConfirmationRequest2.hpp" #include "com/sun/star/task/ErrorCodeIOException.hpp" #include "com/sun/star/task/ErrorCodeRequest.hpp" #include "com/sun/star/task/FutureDocumentVersionProductUpdateRequest.hpp" @@ -73,12 +71,16 @@ #include "tools/rcid.h" // RSC_STRING #include "tools/errinf.hxx" // ErrorHandler, ErrorContext, ... #include "vos/mutex.hxx" +#include "tools/diagnose_ex.h" #include "comphelper/documentconstants.hxx" // ODFVER_012_TEXT #include "svtools/sfxecode.hxx" // ERRCODE_SFX_* #include "vcl/msgbox.hxx" #include "vcl/svapp.hxx" #include "unotools/configmgr.hxx" #include "toolkit/helper/vclunohelper.hxx" +#include "comphelper/namedvaluecollection.hxx" +#include "typelib/typedescription.hxx" +#include "unotools/confignode.hxx" #include "ids.hrc" @@ -88,7 +90,26 @@ #include "iahndl.hxx" -using namespace com::sun::star; +/** === begin UNO using === **/ +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::task::XInteractionContinuation; +using ::com::sun::star::task::XInteractionAbort; +using ::com::sun::star::task::XInteractionApprove; +using ::com::sun::star::task::XInteractionAskLater; +using ::com::sun::star::task::FutureDocumentVersionProductUpdateRequest; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::lang::XInitialization; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::task::XInteractionHandler2; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Any; +using ::com::sun::star::task::XInteractionRequest; +using ::com::sun::star::lang::XMultiServiceFactory; +/** === end UNO using === **/ + +using namespace ::com::sun::star; namespace { @@ -310,47 +331,116 @@ UUIInteractionHelper::tryOtherInteractionHandler( aIt != aEnd; ++aIt) { - uno::Reference< uno::XInterface > xIfc; + if ( handleCustomRequest( rRequest, aIt->ServiceName ) ) + return true; + } + return false; +} - try - { - xIfc = m_xServiceFactory->createInstance(aIt->ServiceName); - } - catch ( uno::RuntimeException const & ) - { - throw; - } - catch ( uno::Exception const & ) +namespace +{ + // ................................................................................................................. + static bool lcl_matchesRequest( const Any& i_rRequest, const ::rtl::OUString& i_rTypeName, const ::rtl::OUString& i_rPropagation ) + { + const ::com::sun::star::uno::TypeDescription aTypeDesc( i_rTypeName ); + const typelib_TypeDescription* pTypeDesc = aTypeDesc.get(); + if ( !pTypeDesc || !pTypeDesc->pWeakRef ) { +#if OSL_DEBUG_LEVEL > 0 + ::rtl::OStringBuffer aMessage; + aMessage.append( "no type found for '" ); + aMessage.append( ::rtl::OUStringToOString( i_rTypeName, RTL_TEXTENCODING_UTF8 ) ); + aMessage.append( "'" ); + OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() ); +#endif + return false; } + const ::com::sun::star::uno::Type aType( pTypeDesc->pWeakRef ); - uno::Reference< lang::XInitialization > - xInitialization( xIfc, uno::UNO_QUERY ); + const bool bExactMatch = ( i_rPropagation.compareToAscii( "named-only" ) == 0 ); + if ( bExactMatch ) + return i_rRequest.getValueType().equals( aType ); - OSL_ENSURE( xInitialization.is(), - "Custom Interactionhandler does not " - "implement mandatory interface XInitialization!" ); - if (xInitialization.is()) - { - uno::Sequence< uno::Any > propertyValues(1); - beans::PropertyValue aProperty; + return i_rRequest.isExtractableTo( aType ); + } +} - aProperty.Name = rtl::OUString::createFromAscii( "Parent" ); - aProperty.Value <<= getParentXWindow(); - propertyValues[ 0 ] <<= aProperty; +// --------------------------------------------------------------------------------------------------------------------- +bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const ::rtl::OUString& i_rServiceName ) const +{ + try + { + Reference< XInteractionHandler2 > xHandler( m_xServiceFactory->createInstance( i_rServiceName ), UNO_QUERY_THROW ); - xInitialization->initialize(propertyValues); + Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY ); + if ( xHandlerInit.is() ) + { + ::comphelper::NamedValueCollection aInitArgs; + aInitArgs.put( "Parent", getParentXWindow() ); + xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() ); } - uno::Reference< task::XInteractionHandler2 > - xIH( xIfc, uno::UNO_QUERY ); - - OSL_ENSURE( xIH.is(), - "Custom Interactionhandler does not " - "implement mandatory interface XInteractionHandler2!" ); - if (xIH.is() && xIH->handleInteractionRequest(rRequest)) + if ( xHandler->handleInteractionRequest( i_rRequest ) ) return true; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return false; +} + +// --------------------------------------------------------------------------------------------------------------------- +bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest ) +{ + // the request + const Any aRequest( rRequest->getRequest() ); + + const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() ); + if ( aCacheHitTest != m_aTypedCustomHandlers.end() ) + return handleCustomRequest( rRequest, aCacheHitTest->second ); + + // the base registration node for "typed" interaction handlers + const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithServiceFactory( + m_xServiceFactory, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Interaction/InteractionHandlers" ) ), + -1, + ::utl::OConfigurationTreeRoot::CM_READONLY + ) ); + + // loop through all registered implementations + const Sequence< ::rtl::OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() ); + const ::rtl::OUString* pHandlerName = aRegisteredHandlers.getConstArray(); + const ::rtl::OUString* pHandlersEnd = aRegisteredHandlers.getConstArray() + aRegisteredHandlers.getLength(); + for ( ; pHandlerName != pHandlersEnd; ++pHandlerName ) + { + const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( *pHandlerName ) ); + const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) ); + + // loop through all the types which the current handler is registered for + const Sequence< ::rtl::OUString > aHandledTypes( aTypesNode.getNodeNames() ); + const ::rtl::OUString* pType = aHandledTypes.getConstArray(); + const ::rtl::OUString* pTypesEnd = aHandledTypes.getConstArray() + aHandledTypes.getLength(); + for ( ; pType != pTypesEnd; ++pType ) + { + // the UNO type is the node name + ::utl::OConfigurationNode aType( aTypesNode.openNode( *pType ) ); + // and there's a child denoting how the responsibility propagates + ::rtl::OUString sPropagation; + OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation ); + if ( lcl_matchesRequest( aRequest, *pType, sPropagation ) ) + { + // retrieve the service/implementation name of the handler + ::rtl::OUString sServiceName; + OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName ); + // cache the information who feels responsible for requests of this type + m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName; + // actually handle the request + return handleCustomRequest( rRequest, sServiceName ); + } + } + } + return false; } @@ -819,24 +909,12 @@ UUIInteractionHelper::handleRequest_impl( handleMacroConfirmRequest( aMacroConfirmRequest.DocumentURL, aMacroConfirmRequest.DocumentStorage, - ODFVER_012_TEXT, + aMacroConfirmRequest.DocumentVersion.getLength() ? aMacroConfirmRequest.DocumentVersion : ODFVER_012_TEXT, aMacroConfirmRequest.DocumentSignatureInformation, rRequest->getContinuations()); return true; } - task::DocumentMacroConfirmationRequest2 aMacroConfirmRequest2; - if (aAnyRequest >>= aMacroConfirmRequest2) - { - handleMacroConfirmRequest( - aMacroConfirmRequest2.DocumentURL, - aMacroConfirmRequest2.DocumentZipStorage, - aMacroConfirmRequest2.DocumentVersion, - aMacroConfirmRequest2.DocumentSignatureInformation, - rRequest->getContinuations()); - return true; - } - task::FutureDocumentVersionProductUpdateRequest aProductUpdateRequest; if (aAnyRequest >>= aProductUpdateRequest) @@ -848,8 +926,14 @@ UUIInteractionHelper::handleRequest_impl( } /////////////////////////////////////////////////////////////// - // Last chance: try to find and use another IH for the request. + // Last chance: interaction handlers registered in the configuration /////////////////////////////////////////////////////////////// + + // typed InteractionHandlers (ooo.Interactions) + if ( handleTypedHandlerImplementations( rRequest ) ) + return true; + + // legacy configuration (ooo.ucb.InteractionHandlers) if (tryOtherInteractionHandler( rRequest )) return true; } @@ -863,6 +947,15 @@ UUIInteractionHelper::handleRequest_impl( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")), uno::Reference< uno::XInterface >()); } + catch( const uno::RuntimeException& ) + { + throw; // allowed to leave here + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return false; } void @@ -997,21 +1090,16 @@ UUIInteractionHelper::getParentProperty() } uno::Reference< awt::XWindow> -UUIInteractionHelper::getParentXWindow() +UUIInteractionHelper::getParentXWindow() const SAL_THROW(()) { osl::MutexGuard aGuard(m_aPropertyMutex); - for (sal_Int32 i = 0; i < m_aProperties.getLength(); ++i) + ::comphelper::NamedValueCollection aProperties( m_aProperties ); + if ( aProperties.has( "Parent" ) ) { - beans::PropertyValue aProperty; - if ((m_aProperties[i] >>= aProperty) - && aProperty. - Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Parent"))) - { - uno::Reference< awt::XWindow > xWindow; - aProperty.Value >>= xWindow; - return xWindow; - } + uno::Reference< awt::XWindow > xWindow; + OSL_VERIFY( aProperties.get( "Parent" ) >>= xWindow ); + return xWindow; } return 0; } @@ -1350,11 +1438,8 @@ UUIInteractionHelper::handleFutureDocumentVersionUpdateRequest( // suitable place), again, and we would only have one place where we remember the s_bDeferredToNextSession // flag. // - // The side effect (well, actually the more important effect) would be that we do not need to burden - // this central implementation with all interactions which are possible. Instead, separate parts of OOo - // can define/implement different requests. (for instance, everything which today is done in the - // css.sdb.InteractionHandler can then be routed through a "normal" interaction handler, where today we - // always need to tell people to instantiate the SDB-version of the handler, not the normal one.) + // Note: The above pattern has been implemented in CWS autorecovery. Now the remaining task is to move the + // handling of this interaction to SFX, again. if ( !s_bDeferredToNextSession ) { |