1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "formdispatchinterceptor.hxx"
28 
29 /** === begin UNO includes === **/
30 /** === end UNO includes === **/
31 
32 #include <tools/debug.hxx>
33 
34 //........................................................................
35 namespace svxform
36 {
37 //........................................................................
38 
39 	/** === begin UNO using === **/
40 	using ::com::sun::star::uno::Reference;
41 	using ::com::sun::star::uno::XInterface;
42 	using ::com::sun::star::uno::UNO_QUERY;
43 	using ::com::sun::star::uno::UNO_QUERY_THROW;
44 	using ::com::sun::star::uno::UNO_SET_THROW;
45 	using ::com::sun::star::uno::Exception;
46 	using ::com::sun::star::uno::RuntimeException;
47 	using ::com::sun::star::uno::Any;
48 	using ::com::sun::star::uno::makeAny;
49 	using ::com::sun::star::uno::Sequence;
50 	using ::com::sun::star::uno::Type;
51     using ::com::sun::star::frame::XDispatchProviderInterception;
52     using ::com::sun::star::frame::XDispatchProviderInterceptor;
53     using ::com::sun::star::lang::XComponent;
54     using ::com::sun::star::util::URL;
55     using ::com::sun::star::frame::XDispatch;
56     using ::com::sun::star::frame::DispatchDescriptor;
57     using ::com::sun::star::frame::XDispatchProvider;
58     using ::com::sun::star::lang::EventObject;
59 	/** === end UNO using === **/
60 
61     //========================================================================
62     //= DispatchInterceptionMultiplexer
63     //========================================================================
64 
65     DBG_NAME(DispatchInterceptionMultiplexer)
66     //------------------------------------------------------------------------
67     DispatchInterceptionMultiplexer::DispatchInterceptionMultiplexer(
68 			    const Reference< XDispatchProviderInterception >& _rxToIntercept, DispatchInterceptor* _pMaster )
69 	    :DispatchInterceptionMultiplexer_BASE(_pMaster && _pMaster->getInterceptorMutex() ? *_pMaster->getInterceptorMutex() : m_aFallback)
70         ,m_aFallback()
71         ,m_pMutex( _pMaster && _pMaster->getInterceptorMutex() ? _pMaster->getInterceptorMutex() : &m_aFallback )
72 	    ,m_xIntercepted(_rxToIntercept)
73 	    ,m_bListening(sal_False)
74 	    ,m_pMaster(_pMaster)
75     {
76 	    DBG_CTOR(DispatchInterceptionMultiplexer,NULL);
77 
78 	    ::osl::MutexGuard aGuard( *m_pMutex );
79 	    ::comphelper::increment(m_refCount);
80 	    if (_rxToIntercept.is())
81 	    {
82 		    _rxToIntercept->registerDispatchProviderInterceptor((XDispatchProviderInterceptor*)this);
83 		    // this should make us the top-level dispatch-provider for the component, via a call to our
84 		    // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill
85 		    Reference< XComponent> xInterceptedComponent(_rxToIntercept, UNO_QUERY);
86 		    if (xInterceptedComponent.is())
87 		    {
88 			    xInterceptedComponent->addEventListener(this);
89 			    m_bListening = sal_True;
90 		    }
91 	    }
92 	    ::comphelper::decrement(m_refCount);
93     }
94 
95     //------------------------------------------------------------------------
96     DispatchInterceptionMultiplexer::~DispatchInterceptionMultiplexer()
97     {
98 	    if (!rBHelper.bDisposed)
99 		    dispose();
100 
101 	    DBG_DTOR(DispatchInterceptionMultiplexer,NULL);
102     }
103 
104     //------------------------------------------------------------------------------
105     Reference< XDispatch > SAL_CALL DispatchInterceptionMultiplexer::queryDispatch( const URL& aURL, const ::rtl::OUString& aTargetFrameName, sal_Int32 nSearchFlags ) throw(RuntimeException)
106     {
107 	    ::osl::MutexGuard aGuard( *m_pMutex );
108 	    Reference< XDispatch> xResult;
109 	    // ask our 'real' interceptor
110 	    if (m_pMaster)
111 		    xResult = m_pMaster->interceptedQueryDispatch( aURL, aTargetFrameName, nSearchFlags);
112 
113 	    // ask our slave provider
114 	    if (!xResult.is() && m_xSlaveDispatcher.is())
115 		    xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
116 
117 	    return xResult;
118     }
119 
120     //------------------------------------------------------------------------------
121     Sequence< Reference< XDispatch > > SAL_CALL
122     DispatchInterceptionMultiplexer::queryDispatches( const Sequence< DispatchDescriptor >& aDescripts ) throw(RuntimeException)
123     {
124 	    ::osl::MutexGuard aGuard( *m_pMutex );
125 	    Sequence< Reference< XDispatch> > aReturn(aDescripts.getLength());
126 	    Reference< XDispatch>* pReturn = aReturn.getArray();
127 	    const DispatchDescriptor* pDescripts = aDescripts.getConstArray();
128 	    for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts)
129 	    {
130 		    *pReturn = queryDispatch(pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags);
131 	    }
132 	    return aReturn;
133     }
134 
135     //------------------------------------------------------------------------------
136     Reference< XDispatchProvider > SAL_CALL DispatchInterceptionMultiplexer::getSlaveDispatchProvider(	) throw(RuntimeException)
137     {
138 	    ::osl::MutexGuard aGuard( *m_pMutex );
139 	    return m_xSlaveDispatcher;
140     }
141 
142     //------------------------------------------------------------------------------
143     void SAL_CALL DispatchInterceptionMultiplexer::setSlaveDispatchProvider(const Reference< XDispatchProvider>& xNewDispatchProvider) throw( RuntimeException )
144     {
145 	    ::osl::MutexGuard aGuard( *m_pMutex );
146 	    m_xSlaveDispatcher = xNewDispatchProvider;
147     }
148 
149     //------------------------------------------------------------------------------
150     Reference< XDispatchProvider> SAL_CALL DispatchInterceptionMultiplexer::getMasterDispatchProvider(void) throw( RuntimeException )
151     {
152 	    ::osl::MutexGuard aGuard( *m_pMutex );
153 	    return m_xMasterDispatcher;
154     }
155 
156     //------------------------------------------------------------------------------
157     void SAL_CALL DispatchInterceptionMultiplexer::setMasterDispatchProvider(const Reference< XDispatchProvider>& xNewSupplier) throw( RuntimeException )
158     {
159 	    ::osl::MutexGuard aGuard( *m_pMutex );
160 	    m_xMasterDispatcher = xNewSupplier;
161     }
162 
163     //------------------------------------------------------------------------------
164     void SAL_CALL DispatchInterceptionMultiplexer::disposing(const EventObject& Source) throw( RuntimeException )
165     {
166 	    if (m_bListening)
167 	    {
168 		    Reference< XDispatchProviderInterception > xIntercepted(m_xIntercepted.get(), UNO_QUERY);
169 		    if (Source.Source == xIntercepted)
170 			    ImplDetach();
171 	    }
172     }
173 
174     //------------------------------------------------------------------------------
175     void DispatchInterceptionMultiplexer::ImplDetach()
176     {
177 	    ::osl::MutexGuard aGuard( *m_pMutex );
178 	    OSL_ENSURE(m_bListening, "DispatchInterceptionMultiplexer::ImplDetach: invalid call!");
179 
180 	    // deregister ourself from the interception component
181 	    Reference< XDispatchProviderInterception > xIntercepted(m_xIntercepted.get(), UNO_QUERY);
182 	    if (xIntercepted.is())
183 		    xIntercepted->releaseDispatchProviderInterceptor(static_cast<XDispatchProviderInterceptor*>(this));
184 
185     //	m_xIntercepted = Reference< XDispatchProviderInterception >();
186 		    // Don't reset m_xIntercepted: It may be needed by our owner to check for which object we were
187 		    // responsible. As we hold the object with a weak reference only, this should be no problem.
188 		    // 88936 - 23.07.2001 - frank.schoenheit@sun.com
189 	    m_pMaster = NULL;
190         m_pMutex = &m_aFallback;
191 	    m_bListening = sal_False;
192     }
193 
194     //------------------------------------------------------------------------------
195     void DispatchInterceptionMultiplexer::disposing()
196     {
197 	    // remove ourself as event listener from the interception component
198 	    if (m_bListening)
199 	    {
200 		    Reference< XComponent> xInterceptedComponent(m_xIntercepted.get(), UNO_QUERY);
201 		    if (xInterceptedComponent.is())
202 			    xInterceptedComponent->removeEventListener(static_cast<XEventListener*>(this));
203 
204 		    // detach from the interception component
205 		    ImplDetach();
206 	    }
207     }
208 
209 //........................................................................
210 } // namespace svxform
211 //........................................................................
212