LCOV - code coverage report
Current view: top level - sfx2/source/notify - eventsupplier.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 139 219 63.5 %
Date: 2014-11-03 Functions: 14 17 82.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <com/sun/star/beans/PropertyValue.hpp>
      21             : 
      22             : #include <com/sun/star/util/URL.hpp>
      23             : 
      24             : #include <com/sun/star/frame/Desktop.hpp>
      25             : #include <com/sun/star/util/URLTransformer.hpp>
      26             : #include <com/sun/star/util/XURLTransformer.hpp>
      27             : #include <tools/urlobj.hxx>
      28             : #include <tools/diagnose_ex.h>
      29             : #include <svl/macitem.hxx>
      30             : #include <sfx2/objsh.hxx>
      31             : #include <sfx2/sfxbasemodel.hxx>
      32             : #include <sfx2/evntconf.hxx>
      33             : #include <unotools/eventcfg.hxx>
      34             : 
      35             : #include <unotools/securityoptions.hxx>
      36             : #include <comphelper/processfactory.hxx>
      37             : #include <comphelper/namedvaluecollection.hxx>
      38             : #include "eventsupplier.hxx"
      39             : 
      40             : #include <sfx2/app.hxx>
      41             : #include <sfx2/sfxresid.hxx>
      42             : 
      43             : #include <sfx2/sfxsids.hrc>
      44             : #include "sfxlocal.hrc"
      45             : #include <sfx2/docfile.hxx>
      46             : #include <sfx2/viewfrm.hxx>
      47             : #include <sfx2/frame.hxx>
      48             : #include <macroloader.hxx>
      49             : 
      50             : 
      51             : 
      52             : #define MACRO_PRFIX         "macro://"
      53             : #define MACRO_POSTFIX       "()"
      54             : 
      55             : using namespace css;
      56             : 
      57             : 
      58             :     //  --- XNameReplace ---
      59             : 
      60           2 : void SAL_CALL SfxEvents_Impl::replaceByName( const OUString & aName, const uno::Any & rElement )
      61             :                                 throw( lang::IllegalArgumentException, container::NoSuchElementException,
      62             :                                        lang::WrappedTargetException, uno::RuntimeException, std::exception )
      63             : {
      64           2 :     ::osl::MutexGuard aGuard( maMutex );
      65             : 
      66             :     // find the event in the list and replace the data
      67           2 :     long nCount = maEventNames.getLength();
      68          42 :     for ( long i=0; i<nCount; i++ )
      69             :     {
      70          42 :         if ( maEventNames[i] == aName )
      71             :         {
      72             :             // check for correct type of the element
      73           2 :             if ( !::comphelper::NamedValueCollection::canExtractFrom( rElement ) )
      74           0 :                 throw lang::IllegalArgumentException();
      75           2 :             ::comphelper::NamedValueCollection const aEventDescriptor( rElement );
      76             : 
      77             :             // create Configuration at first, creation might call this method also and that would overwrite everything
      78             :             // we might have stored before!
      79           2 :             if ( mpObjShell && !mpObjShell->IsLoading() )
      80           2 :                 mpObjShell->SetModified( true );
      81             : 
      82           4 :             ::comphelper::NamedValueCollection aNormalizedDescriptor;
      83           2 :             NormalizeMacro( aEventDescriptor, aNormalizedDescriptor, mpObjShell );
      84             : 
      85           4 :             OUString sType;
      86           4 :             if  (   ( aNormalizedDescriptor.size() == 1 )
      87           0 :                 &&  !aNormalizedDescriptor.has( PROP_EVENT_TYPE ) //TODO
      88           0 :                 &&  ( aNormalizedDescriptor.get( PROP_EVENT_TYPE ) >>= sType )
      89           2 :                 &&  ( sType.isEmpty() )
      90             :                 )
      91             :             {
      92             :                 // An empty event type means no binding. Therefore reset data
      93             :                 // to reflect that state.
      94             :                 // (that's for compatibility only. Nowadays, the Tools/Customize dialog should
      95             :                 // set an empty sequence to indicate the request for resetting the assignment.)
      96             :                 OSL_ENSURE( false, "legacy event assignment format detected" );
      97           0 :                 aNormalizedDescriptor.clear();
      98             :             }
      99             : 
     100           2 :             if ( !aNormalizedDescriptor.empty() )
     101             :             {
     102           2 :                 maEventData[i] <<= aNormalizedDescriptor.getPropertyValues();
     103             :             }
     104             :             else
     105             :             {
     106           0 :                 maEventData[i].clear();
     107             :             }
     108           6 :             return;
     109             :         }
     110             :     }
     111             : 
     112           2 :     throw container::NoSuchElementException();
     113             : }
     114             : 
     115             : 
     116             : //  --- XNameAccess ---
     117             : 
     118        4088 : uno::Any SAL_CALL SfxEvents_Impl::getByName( const OUString& aName )
     119             :                                 throw( container::NoSuchElementException, lang::WrappedTargetException,
     120             :                                        uno::RuntimeException, std::exception )
     121             : {
     122        4088 :     ::osl::MutexGuard aGuard( maMutex );
     123             : 
     124             :     // find the event in the list and return the data
     125             : 
     126        4088 :     long nCount = maEventNames.getLength();
     127             : 
     128       65220 :     for ( long i=0; i<nCount; i++ )
     129             :     {
     130       65220 :         if ( maEventNames[i] == aName )
     131        8176 :             return maEventData[i];
     132             :     }
     133             : 
     134        4088 :     throw container::NoSuchElementException();
     135             : }
     136             : 
     137             : 
     138         134 : uno::Sequence< OUString > SAL_CALL SfxEvents_Impl::getElementNames() throw ( uno::RuntimeException, std::exception )
     139             : {
     140         134 :     return maEventNames;
     141             : }
     142             : 
     143             : 
     144           0 : sal_Bool SAL_CALL SfxEvents_Impl::hasByName( const OUString& aName ) throw ( uno::RuntimeException, std::exception )
     145             : {
     146           0 :     ::osl::MutexGuard aGuard( maMutex );
     147             : 
     148             :     // find the event in the list and return the data
     149             : 
     150           0 :     long nCount = maEventNames.getLength();
     151             : 
     152           0 :     for ( long i=0; i<nCount; i++ )
     153             :     {
     154           0 :         if ( maEventNames[i] == aName )
     155           0 :             return sal_True;
     156             :     }
     157             : 
     158           0 :     return sal_False;
     159             : }
     160             : 
     161             : 
     162             : //  --- XElementAccess ( parent of XNameAccess ) ---
     163             : 
     164           0 : uno::Type SAL_CALL SfxEvents_Impl::getElementType() throw ( uno::RuntimeException, std::exception )
     165             : {
     166           0 :     uno::Type aElementType = ::getCppuType( (const uno::Sequence < beans::PropertyValue > *)0 );
     167           0 :     return aElementType;
     168             : }
     169             : 
     170             : 
     171           0 : sal_Bool SAL_CALL SfxEvents_Impl::hasElements() throw ( uno::RuntimeException, std::exception )
     172             : {
     173           0 :     ::osl::MutexGuard aGuard( maMutex );
     174             : 
     175           0 :     if ( maEventNames.getLength() )
     176           0 :         return sal_True;
     177             :     else
     178           0 :         return sal_False;
     179             : }
     180             : 
     181       71320 : void SfxEvents_Impl::Execute( uno::Any& aEventData, const document::DocumentEvent& aTrigger, SfxObjectShell* pDoc )
     182             : {
     183       71320 :     uno::Sequence < beans::PropertyValue > aProperties;
     184       71320 :     if ( aEventData >>= aProperties )
     185             :     {
     186       69590 :         OUString aType;
     187      139180 :         OUString aScript;
     188      139180 :         OUString aLibrary;
     189      139180 :         OUString aMacroName;
     190             : 
     191       69590 :         sal_Int32 nCount = aProperties.getLength();
     192             : 
     193       69590 :         if ( !nCount )
     194       71320 :             return;
     195             : 
     196       69590 :         sal_Int32 nIndex = 0;
     197      278360 :         while ( nIndex < nCount )
     198             :         {
     199      139180 :             if ( aProperties[ nIndex ].Name == PROP_EVENT_TYPE )
     200       69590 :                 aProperties[ nIndex ].Value >>= aType;
     201       69590 :             else if ( aProperties[ nIndex ].Name == PROP_SCRIPT )
     202       69590 :                 aProperties[ nIndex ].Value >>= aScript;
     203           0 :             else if ( aProperties[ nIndex ].Name == PROP_LIBRARY )
     204           0 :                 aProperties[ nIndex ].Value >>= aLibrary;
     205           0 :             else if ( aProperties[ nIndex ].Name == PROP_MACRO_NAME )
     206           0 :                 aProperties[ nIndex ].Value >>= aMacroName;
     207             :             else {
     208             :                 OSL_FAIL("Unknown property value!");
     209             :             }
     210      139180 :             nIndex += 1;
     211             :         }
     212             : 
     213       69590 :         if (aType == STAR_BASIC && !aScript.isEmpty())
     214             :         {
     215           0 :             uno::Any aAny;
     216           0 :             SfxMacroLoader::loadMacro( aScript, aAny, pDoc );
     217             :         }
     218      139180 :         else if (aType == "Service" ||
     219       69590 :                   aType == "Script")
     220             :         {
     221       69590 :             if ( !aScript.isEmpty() )
     222             :             {
     223             :                 SfxViewFrame* pView = pDoc ?
     224             :                     SfxViewFrame::GetFirst( pDoc ) :
     225           2 :                     SfxViewFrame::Current();
     226             : 
     227           2 :                 uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
     228             : 
     229           4 :                 util::URL aURL;
     230           2 :                 aURL.Complete = aScript;
     231           2 :                 xTrans->parseStrict( aURL );
     232             : 
     233             :                 uno::Reference
     234           4 :                     < frame::XDispatchProvider > xProv;
     235             : 
     236           2 :                 if ( pView != NULL )
     237             :                 {
     238           4 :                     xProv = uno::Reference
     239             :                         < frame::XDispatchProvider > (
     240           4 :                             pView->GetFrame().GetFrameInterface(), uno::UNO_QUERY );
     241             :                 }
     242             :                 else
     243             :                 {
     244           0 :                     xProv = uno::Reference< frame::XDispatchProvider > (
     245             :                                 frame::Desktop::create( ::comphelper::getProcessComponentContext() ),
     246           0 :                                 uno::UNO_QUERY );
     247             :                 }
     248             : 
     249           4 :                 uno::Reference < frame::XDispatch > xDisp;
     250           2 :                 if ( xProv.is() )
     251           2 :                     xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
     252             : 
     253           2 :                 if ( xDisp.is() )
     254             :                 {
     255             : 
     256           2 :                     beans::PropertyValue aEventParam;
     257           2 :                     aEventParam.Value <<= aTrigger;
     258           4 :                     uno::Sequence< beans::PropertyValue > aDispatchArgs( &aEventParam, 1 );
     259           4 :                     xDisp->dispatch( aURL, aDispatchArgs );
     260           2 :                 }
     261             :             }
     262             :         }
     263           0 :         else if ( aType.isEmpty() )
     264             :         {
     265             :             // Empty type means no active binding for the event. Just ignore do nothing.
     266             :         }
     267             :         else
     268             :         {
     269             :             SAL_WARN( "sfx.notify", "notifyEvent(): Unsupported event type" );
     270       69590 :         }
     271       71320 :     }
     272             : }
     273             : 
     274             : 
     275             : // --- ::document::XEventListener ---
     276             : 
     277         842 : void SAL_CALL SfxEvents_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
     278             : {
     279         842 :     ::osl::ClearableMutexGuard aGuard( maMutex );
     280             : 
     281             :     // get the event name, find the coresponding data, execute the data
     282             : 
     283        1590 :     OUString aName   = aEvent.EventName;
     284         842 :     long        nCount  = maEventNames.getLength();
     285         842 :     long        nIndex  = 0;
     286         842 :     bool    bFound  = false;
     287             : 
     288       20008 :     while ( !bFound && ( nIndex < nCount ) )
     289             :     {
     290       18324 :         if ( maEventNames[nIndex] == aName )
     291         748 :             bFound = true;
     292             :         else
     293       17576 :             nIndex += 1;
     294             :     }
     295             : 
     296         842 :     if ( !bFound )
     297         936 :         return;
     298             : 
     299        1496 :     uno::Any aEventData = maEventData[ nIndex ];
     300         748 :     aGuard.clear();
     301        1496 :     Execute( aEventData, document::DocumentEvent(aEvent.Source, aEvent.EventName, NULL, uno::Any()), mpObjShell );
     302             : }
     303             : 
     304             : 
     305             : // --- ::lang::XEventListener ---
     306             : 
     307         154 : void SAL_CALL SfxEvents_Impl::disposing( const lang::EventObject& /*Source*/ ) throw( uno::RuntimeException, std::exception )
     308             : {
     309         154 :     ::osl::MutexGuard aGuard( maMutex );
     310             : 
     311         154 :     if ( mxBroadcaster.is() )
     312             :     {
     313         154 :         mxBroadcaster->removeEventListener( this );
     314         154 :         mxBroadcaster = NULL;
     315         154 :     }
     316         154 : }
     317             : 
     318             : 
     319             : 
     320         154 : SfxEvents_Impl::SfxEvents_Impl( SfxObjectShell* pShell,
     321         154 :                                 uno::Reference< document::XEventBroadcaster > xBroadcaster )
     322             : {
     323             :     // get the list of supported events and store it
     324         154 :     if ( pShell )
     325         154 :         maEventNames = pShell->GetEventNames();
     326             :     else
     327           0 :         maEventNames = GlobalEventConfig().getElementNames();
     328             : 
     329         154 :     maEventData = uno::Sequence < uno::Any > ( maEventNames.getLength() );
     330             : 
     331         154 :     mpObjShell      = pShell;
     332         154 :     mxBroadcaster   = xBroadcaster;
     333             : 
     334         154 :     if ( mxBroadcaster.is() )
     335         154 :         mxBroadcaster->addEventListener( this );
     336         154 : }
     337             : 
     338             : 
     339         308 : SfxEvents_Impl::~SfxEvents_Impl()
     340             : {
     341         308 : }
     342             : 
     343             : 
     344          88 : SvxMacro* SfxEvents_Impl::ConvertToMacro( const uno::Any& rElement, SfxObjectShell* pObjShell, bool bNormalizeMacro )
     345             : {
     346          88 :     SvxMacro* pMacro = NULL;
     347          88 :     uno::Sequence < beans::PropertyValue > aProperties;
     348         176 :     uno::Any aAny;
     349          88 :     if ( bNormalizeMacro )
     350          88 :         NormalizeMacro( rElement, aAny, pObjShell );
     351             :     else
     352           0 :         aAny = rElement;
     353             : 
     354          88 :     if ( aAny >>= aProperties )
     355             :     {
     356          88 :         OUString aType;
     357          88 :         OUString aScriptURL;
     358          88 :         OUString aLibrary;
     359          88 :         OUString aMacroName;
     360             : 
     361          88 :         long nCount = aProperties.getLength();
     362          88 :         long nIndex = 0;
     363             : 
     364          88 :         if ( !nCount )
     365          88 :             return pMacro;
     366             : 
     367           0 :         while ( nIndex < nCount )
     368             :         {
     369           0 :             if ( aProperties[ nIndex ].Name == PROP_EVENT_TYPE )
     370           0 :                 aProperties[ nIndex ].Value >>= aType;
     371           0 :             else if ( aProperties[ nIndex ].Name == PROP_SCRIPT )
     372           0 :                 aProperties[ nIndex ].Value >>= aScriptURL;
     373           0 :             else if ( aProperties[ nIndex ].Name == PROP_LIBRARY )
     374           0 :                 aProperties[ nIndex ].Value >>= aLibrary;
     375           0 :             else if ( aProperties[ nIndex ].Name == PROP_MACRO_NAME )
     376           0 :                 aProperties[ nIndex ].Value >>= aMacroName;
     377             :             else {
     378             :                 OSL_FAIL("Unknown propery value!");
     379             :             }
     380           0 :             nIndex += 1;
     381             :         }
     382             : 
     383             :         // Get the type
     384           0 :         ScriptType  eType( STARBASIC );
     385           0 :         if ( aType == STAR_BASIC )
     386           0 :             eType = STARBASIC;
     387           0 :         else if (aType == "Script" && !aScriptURL.isEmpty())
     388           0 :             eType = EXTENDED_STYPE;
     389           0 :         else if ( aType == SVX_MACRO_LANGUAGE_JAVASCRIPT )
     390           0 :             eType = JAVASCRIPT;
     391             :         else {
     392             :             SAL_WARN( "sfx.notify", "ConvertToMacro: Unknown macro type" );
     393             :         }
     394             : 
     395           0 :         if ( !aMacroName.isEmpty() )
     396             :         {
     397           0 :             if ( aLibrary == "application" )
     398           0 :                 aLibrary = SfxGetpApp()->GetName();
     399             :             else
     400           0 :                 aLibrary = "";
     401           0 :             pMacro = new SvxMacro( aMacroName, aLibrary, eType );
     402             :         }
     403           0 :         else if ( eType == EXTENDED_STYPE )
     404           0 :             pMacro = new SvxMacro( aScriptURL, aType );
     405             :     }
     406             : 
     407          88 :     return pMacro;
     408             : }
     409             : 
     410          88 : void SfxEvents_Impl::NormalizeMacro( const uno::Any& rEvent, uno::Any& rRet, SfxObjectShell* pDoc )
     411             : {
     412          88 :     const ::comphelper::NamedValueCollection aEventDescriptor( rEvent );
     413         176 :     ::comphelper::NamedValueCollection aEventDescriptorOut;
     414             : 
     415          88 :     NormalizeMacro( aEventDescriptor, aEventDescriptorOut, pDoc );
     416             : 
     417         176 :     rRet <<= aEventDescriptorOut.getPropertyValues();
     418          88 : }
     419             : 
     420          90 : void SfxEvents_Impl::NormalizeMacro( const ::comphelper::NamedValueCollection& i_eventDescriptor,
     421             :         ::comphelper::NamedValueCollection& o_normalizedDescriptor, SfxObjectShell* i_document )
     422             : {
     423          90 :     SfxObjectShell* pDoc = i_document;
     424          90 :     if ( !pDoc )
     425           0 :         pDoc = SfxObjectShell::Current();
     426             : 
     427          90 :     OUString aType = i_eventDescriptor.getOrDefault( PROP_EVENT_TYPE, OUString() );
     428         180 :     OUString aScript = i_eventDescriptor.getOrDefault( PROP_SCRIPT, OUString() );
     429         180 :     OUString aLibrary = i_eventDescriptor.getOrDefault( PROP_LIBRARY, OUString() );
     430         180 :     OUString aMacroName = i_eventDescriptor.getOrDefault( PROP_MACRO_NAME, OUString() );
     431             : 
     432          90 :     if ( !aType.isEmpty() )
     433           2 :         o_normalizedDescriptor.put( PROP_EVENT_TYPE, aType );
     434          90 :     if ( !aScript.isEmpty() )
     435           2 :         o_normalizedDescriptor.put( PROP_SCRIPT, aScript );
     436             : 
     437          90 :     if ( aType == STAR_BASIC )
     438             :     {
     439           0 :         if ( !aScript.isEmpty() )
     440             :         {
     441           0 :             if ( aMacroName.isEmpty() || aLibrary.isEmpty() )
     442             :             {
     443           0 :                 sal_Int32 nHashPos = aScript.indexOf( '/', 8 );
     444           0 :                 sal_Int32 nArgsPos = aScript.indexOf( '(' );
     445           0 :                 if ( ( nHashPos != -1 ) && ( nArgsPos == -1 || nHashPos < nArgsPos ) )
     446             :                 {
     447           0 :                     OUString aBasMgrName( INetURLObject::decode( aScript.copy( 8, nHashPos-8 ), '%', INetURLObject::DECODE_WITH_CHARSET ) );
     448           0 :                     if ( aBasMgrName == "." )
     449           0 :                         aLibrary = pDoc->GetTitle();
     450             :                     else
     451           0 :                         aLibrary = SfxGetpApp()->GetName();
     452             : 
     453             :                     // Get the macro name
     454           0 :                     aMacroName = aScript.copy( nHashPos+1, nArgsPos - nHashPos - 1 );
     455             :                 }
     456             :                 else
     457             :                 {
     458             :                     SAL_WARN( "sfx.notify", "ConvertToMacro: Unknown macro url format" );
     459             :                 }
     460             :             }
     461             :         }
     462           0 :         else if ( !aMacroName.isEmpty() )
     463             :         {
     464           0 :             aScript = OUString( MACRO_PRFIX  );
     465           0 :             if ( aLibrary != SfxGetpApp()->GetName() && aLibrary != "StarDesktop" && aLibrary != "application" )
     466           0 :                 aScript += OUString('.');
     467             : 
     468           0 :             aScript += OUString('/');
     469           0 :             aScript += aMacroName;
     470           0 :             aScript += OUString( MACRO_POSTFIX  );
     471             :         }
     472             :         else
     473             :             // wrong properties
     474          90 :             return;
     475             : 
     476           0 :         if (aLibrary != "document")
     477             :         {
     478           0 :             if ( aLibrary.isEmpty() || (pDoc && ( aLibrary == pDoc->GetTitle( SFX_TITLE_APINAME ) || aLibrary == pDoc->GetTitle() )) )
     479           0 :                 aLibrary = "document";
     480             :             else
     481           0 :                 aLibrary = "application";
     482             :         }
     483             : 
     484           0 :         o_normalizedDescriptor.put( PROP_SCRIPT, aScript );
     485           0 :         o_normalizedDescriptor.put( PROP_LIBRARY, aLibrary );
     486           0 :         o_normalizedDescriptor.put( PROP_MACRO_NAME, aMacroName );
     487          90 :     }
     488         951 : }
     489             : 
     490             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10