1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 10 * OpenOffice.org is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License version 3 12 * only, as published by the Free Software Foundation. 13 * 14 * OpenOffice.org is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License version 3 for more details 18 * (a copy is included in the LICENSE file that accompanied this code). 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * version 3 along with OpenOffice.org. If not, see 22 * <http://www.openoffice.org/license.html> 23 * for a copy of the LGPLv3 License. 24 * 25 ************************************************************************/ 26 27 // MARKER(update_precomp.py): autogen include statement, do not remove 28 #include "precompiled_dbaccess.hxx" 29 30 #include "documenteventexecutor.hxx" 31 32 /** === begin UNO includes === **/ 33 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp> 34 #include <com/sun/star/util/XURLTransformer.hpp> 35 #include <com/sun/star/frame/XModel.hpp> 36 #include <com/sun/star/frame/XDispatchProvider.hpp> 37 /** === end UNO includes === **/ 38 39 #include <comphelper/componentcontext.hxx> 40 #include <comphelper/namedvaluecollection.hxx> 41 #include <cppuhelper/weakref.hxx> 42 #include <tools/diagnose_ex.h> 43 #include <vcl/svapp.hxx> 44 #include <vos/mutex.hxx> 45 46 //........................................................................ 47 namespace dbaccess 48 { 49 //........................................................................ 50 51 /** === begin UNO using === **/ 52 using ::com::sun::star::uno::Reference; 53 using ::com::sun::star::uno::XInterface; 54 using ::com::sun::star::uno::UNO_QUERY; 55 using ::com::sun::star::uno::UNO_QUERY_THROW; 56 using ::com::sun::star::uno::UNO_SET_THROW; 57 using ::com::sun::star::uno::Exception; 58 using ::com::sun::star::uno::RuntimeException; 59 using ::com::sun::star::uno::Any; 60 using ::com::sun::star::uno::makeAny; 61 using ::com::sun::star::uno::Sequence; 62 using ::com::sun::star::uno::Type; 63 using ::com::sun::star::uno::WeakReference; 64 using ::com::sun::star::document::XDocumentEventBroadcaster; 65 using ::com::sun::star::document::XEventsSupplier; 66 using ::com::sun::star::container::XNameAccess; 67 using ::com::sun::star::frame::XModel; 68 using ::com::sun::star::util::XURLTransformer; 69 using ::com::sun::star::frame::XDispatchProvider; 70 using ::com::sun::star::frame::XDispatch; 71 using ::com::sun::star::util::URL; 72 using ::com::sun::star::beans::PropertyValue; 73 using ::com::sun::star::frame::XController; 74 using ::com::sun::star::document::DocumentEvent; 75 /** === end UNO using === **/ 76 using namespace ::com::sun::star; 77 78 //==================================================================== 79 //= DocumentEventExecutor_Data 80 //==================================================================== 81 struct DocumentEventExecutor_Data 82 { 83 WeakReference< XEventsSupplier > xDocument; 84 Reference< XURLTransformer > xURLTransformer; 85 86 DocumentEventExecutor_Data( const Reference< XEventsSupplier >& _rxDocument ) 87 :xDocument( _rxDocument ) 88 { 89 } 90 }; 91 92 //-------------------------------------------------------------------- 93 namespace 94 { 95 static void lcl_dispatchScriptURL_throw( DocumentEventExecutor_Data& _rDocExecData, 96 const ::rtl::OUString& _rScriptURL, const DocumentEvent& _rTrigger ) 97 { 98 Reference< XModel > xDocument( _rDocExecData.xDocument.get(), UNO_QUERY_THROW ); 99 100 Reference< XController > xController( xDocument->getCurrentController() ); 101 Reference< XDispatchProvider > xDispProv; 102 if ( xController.is() ) 103 xDispProv.set( xController->getFrame(), UNO_QUERY ); 104 if ( !xDispProv.is() ) 105 { 106 OSL_ENSURE( false, "lcl_dispatchScriptURL_throw: no controller/frame? How should I dispatch?" ); 107 return; 108 } 109 110 URL aScriptURL; 111 aScriptURL.Complete = _rScriptURL; 112 if ( _rDocExecData.xURLTransformer.is() ) 113 _rDocExecData.xURLTransformer->parseStrict( aScriptURL ); 114 115 // unfortunately, executing a script can trigger all kind of complex stuff, and unfortunately, not 116 // every component involved into this properly cares for thread safety. To be on the safe side, 117 // we lock the solar mutex here. 118 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 119 120 Reference< XDispatch > xDispatch( xDispProv->queryDispatch( aScriptURL, ::rtl::OUString(), 0 ) ); 121 if ( !xDispatch.is() ) 122 { 123 OSL_ENSURE( false, "lcl_dispatchScriptURL_throw: no dispatcher for the script URL!" ); 124 return; 125 } 126 127 PropertyValue aEventParam; 128 aEventParam.Value <<= _rTrigger; 129 Sequence< PropertyValue > aDispatchArgs( &aEventParam, 1 ); 130 xDispatch->dispatch( aScriptURL, aDispatchArgs ); 131 } 132 } 133 134 //==================================================================== 135 //= DocumentEventExecutor 136 //==================================================================== 137 //-------------------------------------------------------------------- 138 DocumentEventExecutor::DocumentEventExecutor( const ::comphelper::ComponentContext& _rContext, 139 const Reference< XEventsSupplier >& _rxDocument ) 140 :m_pData( new DocumentEventExecutor_Data( _rxDocument ) ) 141 { 142 Reference< XDocumentEventBroadcaster > xBroadcaster( _rxDocument, UNO_QUERY_THROW ); 143 144 osl_incrementInterlockedCount( &m_refCount ); 145 { 146 xBroadcaster->addDocumentEventListener( this ); 147 } 148 osl_decrementInterlockedCount( &m_refCount ); 149 150 try 151 { 152 _rContext.createComponent( "com.sun.star.util.URLTransformer", m_pData->xURLTransformer ); 153 } 154 catch( const Exception& ) 155 { 156 DBG_UNHANDLED_EXCEPTION(); 157 } 158 } 159 160 //-------------------------------------------------------------------- 161 DocumentEventExecutor::~DocumentEventExecutor() 162 { 163 } 164 165 //-------------------------------------------------------------------- 166 void SAL_CALL DocumentEventExecutor::documentEventOccured( const DocumentEvent& _Event ) throw (RuntimeException) 167 { 168 Reference< XEventsSupplier > xEventsSupplier( m_pData->xDocument.get(), UNO_QUERY ); 169 if ( !xEventsSupplier.is() ) 170 { 171 OSL_ENSURE( false, "DocumentEventExecutor::documentEventOccured: no document anymore, but still being notified?" ); 172 return; 173 } 174 175 Reference< XModel > xDocument( xEventsSupplier, UNO_QUERY_THROW ); 176 177 try 178 { 179 Reference< XNameAccess > xDocEvents( xEventsSupplier->getEvents().get(), UNO_SET_THROW ); 180 if ( !xDocEvents->hasByName( _Event.EventName ) ) 181 { 182 // this is worth an assertion: We are listener at the very same document which we just asked 183 // for its events. So when EventName is fired, why isn't it supported by xDocEvents? 184 OSL_ENSURE( false, "DocumentEventExecutor::documentEventOccured: an unsupported event is notified!" ); 185 return; 186 } 187 188 const ::comphelper::NamedValueCollection aScriptDescriptor( xDocEvents->getByName( _Event.EventName ) ); 189 190 191 ::rtl::OUString sEventType; 192 bool bScriptAssigned = aScriptDescriptor.get_ensureType( "EventType", sEventType ); 193 194 ::rtl::OUString sScript; 195 bScriptAssigned = bScriptAssigned && aScriptDescriptor.get_ensureType( "Script", sScript ); 196 197 if ( !bScriptAssigned ) 198 // no script is assigned to this event 199 return; 200 201 bool bDispatchScriptURL = 202 ( sEventType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Script" ) ) 203 || sEventType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Service" ) ) 204 ); 205 bool bNonEmptyScript = sScript.getLength() != 0; 206 207 OSL_ENSURE( bDispatchScriptURL && bNonEmptyScript, 208 "DocumentEventExecutor::documentEventOccured: invalid/unsupported script descriptor" ); 209 210 if ( bDispatchScriptURL && bNonEmptyScript ) 211 { 212 lcl_dispatchScriptURL_throw( *m_pData, sScript, _Event ); 213 } 214 } 215 catch( const RuntimeException& ) { throw; } 216 catch( const Exception& ) 217 { 218 DBG_UNHANDLED_EXCEPTION(); 219 } 220 } 221 222 //-------------------------------------------------------------------- 223 void SAL_CALL DocumentEventExecutor::disposing( const lang::EventObject& /*_Source*/ ) throw (RuntimeException) 224 { 225 // not interested in 226 } 227 228 229 //........................................................................ 230 } // namespace dbaccess 231 //........................................................................ 232