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_svx.hxx"
29 
30 #include "formdispatchinterceptor.hxx"
31 
32 /** === begin UNO includes === **/
33 /** === end UNO includes === **/
34 
35 #include <tools/debug.hxx>
36 
37 //........................................................................
38 namespace svxform
39 {
40 //........................................................................
41 
42 	/** === begin UNO using === **/
43 	using ::com::sun::star::uno::Reference;
44 	using ::com::sun::star::uno::XInterface;
45 	using ::com::sun::star::uno::UNO_QUERY;
46 	using ::com::sun::star::uno::UNO_QUERY_THROW;
47 	using ::com::sun::star::uno::UNO_SET_THROW;
48 	using ::com::sun::star::uno::Exception;
49 	using ::com::sun::star::uno::RuntimeException;
50 	using ::com::sun::star::uno::Any;
51 	using ::com::sun::star::uno::makeAny;
52 	using ::com::sun::star::uno::Sequence;
53 	using ::com::sun::star::uno::Type;
54     using ::com::sun::star::frame::XDispatchProviderInterception;
55     using ::com::sun::star::frame::XDispatchProviderInterceptor;
56     using ::com::sun::star::lang::XComponent;
57     using ::com::sun::star::util::URL;
58     using ::com::sun::star::frame::XDispatch;
59     using ::com::sun::star::frame::DispatchDescriptor;
60     using ::com::sun::star::frame::XDispatchProvider;
61     using ::com::sun::star::lang::EventObject;
62 	/** === end UNO using === **/
63 
64     //========================================================================
65     //= DispatchInterceptionMultiplexer
66     //========================================================================
67 
68     DBG_NAME(DispatchInterceptionMultiplexer)
69     //------------------------------------------------------------------------
70     DispatchInterceptionMultiplexer::DispatchInterceptionMultiplexer(
71 			    const Reference< XDispatchProviderInterception >& _rxToIntercept, DispatchInterceptor* _pMaster )
72 	    :DispatchInterceptionMultiplexer_BASE(_pMaster && _pMaster->getInterceptorMutex() ? *_pMaster->getInterceptorMutex() : m_aFallback)
73         ,m_aFallback()
74         ,m_pMutex( _pMaster && _pMaster->getInterceptorMutex() ? _pMaster->getInterceptorMutex() : &m_aFallback )
75 	    ,m_xIntercepted(_rxToIntercept)
76 	    ,m_bListening(sal_False)
77 	    ,m_pMaster(_pMaster)
78     {
79 	    DBG_CTOR(DispatchInterceptionMultiplexer,NULL);
80 
81 	    ::osl::MutexGuard aGuard( *m_pMutex );
82 	    ::comphelper::increment(m_refCount);
83 	    if (_rxToIntercept.is())
84 	    {
85 		    _rxToIntercept->registerDispatchProviderInterceptor((XDispatchProviderInterceptor*)this);
86 		    // this should make us the top-level dispatch-provider for the component, via a call to our
87 		    // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill
88 		    Reference< XComponent> xInterceptedComponent(_rxToIntercept, UNO_QUERY);
89 		    if (xInterceptedComponent.is())
90 		    {
91 			    xInterceptedComponent->addEventListener(this);
92 			    m_bListening = sal_True;
93 		    }
94 	    }
95 	    ::comphelper::decrement(m_refCount);
96     }
97 
98     //------------------------------------------------------------------------
99     DispatchInterceptionMultiplexer::~DispatchInterceptionMultiplexer()
100     {
101 	    if (!rBHelper.bDisposed)
102 		    dispose();
103 
104 	    DBG_DTOR(DispatchInterceptionMultiplexer,NULL);
105     }
106 
107     //------------------------------------------------------------------------------
108     Reference< XDispatch > SAL_CALL DispatchInterceptionMultiplexer::queryDispatch( const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags ) throw(RuntimeException)
109     {
110 	    ::osl::MutexGuard aGuard( *m_pMutex );
111 	    Reference< XDispatch> xResult;
112 	    // ask our 'real' interceptor
113 	    if (m_pMaster)
114 		    xResult = m_pMaster->interceptedQueryDispatch( aURL, aTargetFrameName, nSearchFlags);
115 
116 	    // ask our slave provider
117 	    if (!xResult.is() && m_xSlaveDispatcher.is())
118 		    xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
119 
120 	    return xResult;
121     }
122 
123     //------------------------------------------------------------------------------
124     Sequence< Reference< XDispatch > > SAL_CALL
125     DispatchInterceptionMultiplexer::queryDispatches( const Sequence< DispatchDescriptor >& aDescripts ) throw(RuntimeException)
126     {
127 	    ::osl::MutexGuard aGuard( *m_pMutex );
128 	    Sequence< Reference< XDispatch> > aReturn(aDescripts.getLength());
129 	    Reference< XDispatch>* pReturn = aReturn.getArray();
130 	    const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
131 	    for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts)
132 	    {
133 		    *pReturn = queryDispatch(pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags);
134 	    }
135 	    return aReturn;
136     }
137 
138     //------------------------------------------------------------------------------
139     Reference< XDispatchProvider > SAL_CALL DispatchInterceptionMultiplexer::getSlaveDispatchProvider(	) throw(RuntimeException)
140     {
141 	    ::osl::MutexGuard aGuard( *m_pMutex );
142 	    return m_xSlaveDispatcher;
143     }
144 
145     //------------------------------------------------------------------------------
146     void SAL_CALL DispatchInterceptionMultiplexer::setSlaveDispatchProvider(const Reference< XDispatchProvider>& xNewDispatchProvider) throw( RuntimeException )
147     {
148 	    ::osl::MutexGuard aGuard( *m_pMutex );
149 	    m_xSlaveDispatcher = xNewDispatchProvider;
150     }
151 
152     //------------------------------------------------------------------------------
153     Reference< XDispatchProvider> SAL_CALL DispatchInterceptionMultiplexer::getMasterDispatchProvider(void) throw( RuntimeException )
154     {
155 	    ::osl::MutexGuard aGuard( *m_pMutex );
156 	    return m_xMasterDispatcher;
157     }
158 
159     //------------------------------------------------------------------------------
160     void SAL_CALL DispatchInterceptionMultiplexer::setMasterDispatchProvider(const Reference< XDispatchProvider>& xNewSupplier) throw( RuntimeException )
161     {
162 	    ::osl::MutexGuard aGuard( *m_pMutex );
163 	    m_xMasterDispatcher = xNewSupplier;
164     }
165 
166     //------------------------------------------------------------------------------
167     void SAL_CALL DispatchInterceptionMultiplexer::disposing(const EventObject& Source) throw( RuntimeException )
168     {
169 	    if (m_bListening)
170 	    {
171 		    Reference< XDispatchProviderInterception > xIntercepted(m_xIntercepted.get(), UNO_QUERY);
172 		    if (Source.Source == xIntercepted)
173 			    ImplDetach();
174 	    }
175     }
176 
177     //------------------------------------------------------------------------------
178     void DispatchInterceptionMultiplexer::ImplDetach()
179     {
180 	    ::osl::MutexGuard aGuard( *m_pMutex );
181 	    OSL_ENSURE(m_bListening, "DispatchInterceptionMultiplexer::ImplDetach: invalid call!");
182 
183 	    // deregister ourself from the interception component
184 	    Reference< XDispatchProviderInterception > xIntercepted(m_xIntercepted.get(), UNO_QUERY);
185 	    if (xIntercepted.is())
186 		    xIntercepted->releaseDispatchProviderInterceptor(static_cast<XDispatchProviderInterceptor*>(this));
187 
188     //	m_xIntercepted = Reference< XDispatchProviderInterception >();
189 		    // Don't reset m_xIntercepted: It may be needed by our owner to check for which object we were
190 		    // responsible. As we hold the object with a weak reference only, this should be no problem.
191 		    // 88936 - 23.07.2001 - frank.schoenheit@sun.com
192 	    m_pMaster = NULL;
193         m_pMutex = &m_aFallback;
194 	    m_bListening = sal_False;
195     }
196 
197     //------------------------------------------------------------------------------
198     void DispatchInterceptionMultiplexer::disposing()
199     {
200 	    // remove ourself as event listener from the interception component
201 	    if (m_bListening)
202 	    {
203 		    Reference< XComponent> xInterceptedComponent(m_xIntercepted.get(), UNO_QUERY);
204 		    if (xInterceptedComponent.is())
205 			    xInterceptedComponent->removeEventListener(static_cast<XEventListener*>(this));
206 
207 		    // detach from the interception component
208 		    ImplDetach();
209 	    }
210     }
211 
212 //........................................................................
213 } // namespace svxform
214 //........................................................................
215