1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_embeddedobj.hxx"
30 #include <com/sun/star/embed/EmbedStates.hpp>
31 #include <cppuhelper/weak.hxx>
32 
33 #include "intercept.hxx"
34 #include "docholder.hxx"
35 #include "commonembobj.hxx"
36 
37 using namespace ::com::sun::star;
38 
39 
40 #define IUL 6
41 
42 
43 uno::Sequence< ::rtl::OUString > Interceptor::m_aInterceptedURL(IUL);
44 
45 struct equalOUString
46 {
47 	bool operator()(
48 		const rtl::OUString& rKey1,
49 		const rtl::OUString& rKey2 ) const
50 	{
51 		return !!( rKey1 == rKey2 );
52 	}
53 };
54 
55 
56 struct hashOUString
57 {
58 	size_t operator()( const rtl::OUString& rName ) const
59 	{
60 		return rName.hashCode();
61 	}
62 };
63 
64 
65 
66 class StatusChangeListenerContainer
67 	: public ::cppu::OMultiTypeInterfaceContainerHelperVar<
68 rtl::OUString,hashOUString,equalOUString>
69 {
70 public:
71 	StatusChangeListenerContainer( ::osl::Mutex& aMutex )
72 		:  cppu::OMultiTypeInterfaceContainerHelperVar<
73 	rtl::OUString,hashOUString,equalOUString>(aMutex)
74 	{
75 	}
76 };
77 
78 
79 void Interceptor::DisconnectDocHolder()
80 {
81 	osl::MutexGuard aGuard( m_aMutex );
82 	m_pDocHolder = NULL;
83 }
84 
85 void SAL_CALL
86 Interceptor::addEventListener(
87 	const uno::Reference<lang::XEventListener >& Listener )
88 	throw( uno::RuntimeException )
89 {
90 	osl::MutexGuard aGuard( m_aMutex );
91 
92 	if ( ! m_pDisposeEventListeners )
93 		m_pDisposeEventListeners =
94 			new cppu::OInterfaceContainerHelper( m_aMutex );
95 
96 	m_pDisposeEventListeners->addInterface( Listener );
97 }
98 
99 
100 void SAL_CALL
101 Interceptor::removeEventListener(
102 	const uno::Reference< lang::XEventListener >& Listener )
103 	throw( uno::RuntimeException )
104 {
105 	osl::MutexGuard aGuard( m_aMutex );
106 
107 	if ( m_pDisposeEventListeners )
108 		m_pDisposeEventListeners->removeInterface( Listener );
109 }
110 
111 
112 Interceptor::Interceptor( DocumentHolder* pDocHolder )
113 	: m_pDocHolder( pDocHolder ),
114 	  m_pDisposeEventListeners(0),
115 	  m_pStatCL(0)
116 {
117 	m_aInterceptedURL[0] = rtl::OUString(
118 		RTL_CONSTASCII_USTRINGPARAM(".uno:Save"));
119 	m_aInterceptedURL[1] = rtl::OUString(
120 		RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAll"));
121 	m_aInterceptedURL[2] = rtl::OUString(
122 		RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc"));
123 	m_aInterceptedURL[3] = rtl::OUString(
124 		RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin"));
125 	m_aInterceptedURL[4] = rtl::OUString(
126 		RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame"));
127 	m_aInterceptedURL[5] = rtl::OUString(
128 		RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs"));
129 
130 }
131 
132 
133 Interceptor::~Interceptor()
134 {
135 	if( m_pDisposeEventListeners )
136 		delete m_pDisposeEventListeners;
137 
138 	if(m_pStatCL)
139 		delete m_pStatCL;
140 }
141 
142 
143 
144 //XDispatch
145 void SAL_CALL
146 Interceptor::dispatch(
147 	const util::URL& URL,
148 	const uno::Sequence<
149 	beans::PropertyValue >& Arguments )
150 	throw (uno::RuntimeException)
151 {
152 	osl::MutexGuard aGuard(m_aMutex);
153 	if( m_pDocHolder )
154 	{
155 		if(URL.Complete == m_aInterceptedURL[0])
156 			m_pDocHolder->GetEmbedObject()->SaveObject_Impl();
157 		else if(URL.Complete == m_aInterceptedURL[2] ||
158 				URL.Complete == m_aInterceptedURL[3] ||
159 				URL.Complete == m_aInterceptedURL[4])
160 		{
161 			try {
162 				m_pDocHolder->GetEmbedObject()->changeState( embed::EmbedStates::RUNNING );
163 			}
164 			catch( uno::Exception& )
165 			{
166 			}
167 		}
168 		else if ( URL.Complete == m_aInterceptedURL[5] )
169 		{
170 			uno::Sequence< beans::PropertyValue > aNewArgs = Arguments;
171 			sal_Int32 nInd = 0;
172 
173 			while( nInd < aNewArgs.getLength() )
174 			{
175 				if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) )
176 				{
177 					aNewArgs[nInd].Value <<= sal_True;
178 					break;
179 				}
180 				nInd++;
181 			}
182 
183 			if ( nInd == aNewArgs.getLength() )
184 			{
185 				aNewArgs.realloc( nInd + 1 );
186 				aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" );
187 				aNewArgs[nInd].Value <<= sal_True;
188 			}
189 
190 			uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
191 				URL, ::rtl::OUString::createFromAscii( "_self" ), 0 );
192 			if ( xDispatch.is() )
193 				xDispatch->dispatch( URL, aNewArgs );
194 		}
195 	}
196 }
197 
198 void SAL_CALL
199 Interceptor::addStatusListener(
200 	const uno::Reference<
201 	frame::XStatusListener >& Control,
202 	const util::URL& URL )
203 	throw (
204 		uno::RuntimeException
205 	)
206 {
207 	if(!Control.is())
208 		return;
209 
210 	if(URL.Complete == m_aInterceptedURL[0])
211 	{   // Save
212 		frame::FeatureStateEvent aStateEvent;
213 		aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
214 		aStateEvent.FeatureDescriptor = rtl::OUString(
215 			RTL_CONSTASCII_USTRINGPARAM("Update"));
216 		aStateEvent.IsEnabled = sal_True;
217 		aStateEvent.Requery = sal_False;
218 		aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($1) ")) + m_pDocHolder->GetTitle() );
219 		Control->statusChanged(aStateEvent);
220 
221 		{
222 			osl::MutexGuard aGuard(m_aMutex);
223 			if(!m_pStatCL)
224 				m_pStatCL =
225 					new StatusChangeListenerContainer(m_aMutex);
226 		}
227 
228 		m_pStatCL->addInterface(URL.Complete,Control);
229 		return;
230 	}
231 
232 	sal_Int32 i = 2;
233 	if(URL.Complete == m_aInterceptedURL[i] ||
234 	   URL.Complete == m_aInterceptedURL[++i] ||
235 	   URL.Complete == m_aInterceptedURL[++i] )
236 	{   // Close and return
237 		frame::FeatureStateEvent aStateEvent;
238 		aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
239 		aStateEvent.FeatureDescriptor = rtl::OUString(
240 			RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
241 		aStateEvent.IsEnabled = sal_True;
242 		aStateEvent.Requery = sal_False;
243 		aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($2) ")) + m_pDocHolder->GetTitle() );
244 		Control->statusChanged(aStateEvent);
245 
246 
247 		{
248 			osl::MutexGuard aGuard(m_aMutex);
249 			if(!m_pStatCL)
250 				m_pStatCL =
251 					new StatusChangeListenerContainer(m_aMutex);
252 		}
253 
254 		m_pStatCL->addInterface(URL.Complete,Control);
255 		return;
256 	}
257 
258 	if(URL.Complete == m_aInterceptedURL[5])
259 	{   // SaveAs
260 		frame::FeatureStateEvent aStateEvent;
261 		aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
262 		aStateEvent.FeatureDescriptor = rtl::OUString(
263 			RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
264 		aStateEvent.IsEnabled = sal_True;
265 		aStateEvent.Requery = sal_False;
266 		aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)")));
267 		Control->statusChanged(aStateEvent);
268 
269 		{
270 			osl::MutexGuard aGuard(m_aMutex);
271 			if(!m_pStatCL)
272 				m_pStatCL =
273 					new StatusChangeListenerContainer(m_aMutex);
274 		}
275 
276 		m_pStatCL->addInterface(URL.Complete,Control);
277 		return;
278 	}
279 
280 }
281 
282 
283 void SAL_CALL
284 Interceptor::removeStatusListener(
285 	const uno::Reference<
286 	frame::XStatusListener >& Control,
287 	const util::URL& URL )
288 	throw (
289 		uno::RuntimeException
290 	)
291 {
292 	if(!(Control.is() && m_pStatCL))
293 		return;
294 	else {
295 		m_pStatCL->removeInterface(URL.Complete,Control);
296 		return;
297 	}
298 }
299 
300 
301 //XInterceptorInfo
302 uno::Sequence< ::rtl::OUString >
303 SAL_CALL
304 Interceptor::getInterceptedURLs(  )
305 	throw (
306 		uno::RuntimeException
307 	)
308 {
309 	// now implemented as update
310 
311 	return m_aInterceptedURL;
312 }
313 
314 
315 // XDispatchProvider
316 
317 uno::Reference< frame::XDispatch > SAL_CALL
318 Interceptor::queryDispatch(
319 	const util::URL& URL,
320 	const ::rtl::OUString& TargetFrameName,
321 	sal_Int32 SearchFlags )
322 	throw (
323 		uno::RuntimeException
324 	)
325 {
326 	osl::MutexGuard aGuard(m_aMutex);
327 	if(URL.Complete == m_aInterceptedURL[0])
328 		return (frame::XDispatch*)this;
329 	else if(URL.Complete == m_aInterceptedURL[1])
330 		return (frame::XDispatch*)0   ;
331 	else if(URL.Complete == m_aInterceptedURL[2])
332 		return (frame::XDispatch*)this;
333 	else if(URL.Complete == m_aInterceptedURL[3])
334 		return (frame::XDispatch*)this;
335 	else if(URL.Complete == m_aInterceptedURL[4])
336 		return (frame::XDispatch*)this;
337 	else if(URL.Complete == m_aInterceptedURL[5])
338 		return (frame::XDispatch*)this;
339 	else {
340 		if(m_xSlaveDispatchProvider.is())
341 			return m_xSlaveDispatchProvider->queryDispatch(
342 				URL,TargetFrameName,SearchFlags);
343 		else
344 			return uno::Reference<frame::XDispatch>(0);
345 	}
346 }
347 
348 uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL
349 Interceptor::queryDispatches(
350 	const uno::Sequence<frame::DispatchDescriptor >& Requests )
351 	throw (
352 		uno::RuntimeException
353 	)
354 {
355 	uno::Sequence< uno::Reference< frame::XDispatch > > aRet;
356 	osl::MutexGuard aGuard(m_aMutex);
357 	if(m_xSlaveDispatchProvider.is())
358 		aRet = m_xSlaveDispatchProvider->queryDispatches(Requests);
359 	else
360 		aRet.realloc(Requests.getLength());
361 
362 	for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
363 		if(m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete)
364 			aRet[i] = (frame::XDispatch*) this;
365 		else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete)
366 			aRet[i] = (frame::XDispatch*) 0;
367 		else if(m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete)
368 			aRet[i] = (frame::XDispatch*) this;
369 		else if(m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete)
370 			aRet[i] = (frame::XDispatch*) this;
371 		else if(m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete)
372 			aRet[i] = (frame::XDispatch*) this;
373 		else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete)
374 			aRet[i] = (frame::XDispatch*) this;
375 
376 	return aRet;
377 }
378 
379 
380 
381 //XDispatchProviderInterceptor
382 
383 uno::Reference< frame::XDispatchProvider > SAL_CALL
384 Interceptor::getSlaveDispatchProvider(  )
385 	throw (
386 		uno::RuntimeException
387 	)
388 {
389 	osl::MutexGuard aGuard(m_aMutex);
390 	return m_xSlaveDispatchProvider;
391 }
392 
393 void SAL_CALL
394 Interceptor::setSlaveDispatchProvider(
395 	const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider )
396 	throw (
397 		uno::RuntimeException
398 	)
399 {
400 	osl::MutexGuard aGuard(m_aMutex);
401 	m_xSlaveDispatchProvider = NewDispatchProvider;
402 }
403 
404 
405 uno::Reference< frame::XDispatchProvider > SAL_CALL
406 Interceptor::getMasterDispatchProvider(  )
407 	throw (
408 		uno::RuntimeException
409 	)
410 {
411 	osl::MutexGuard aGuard(m_aMutex);
412 	return m_xMasterDispatchProvider;
413 }
414 
415 
416 void SAL_CALL
417 Interceptor::setMasterDispatchProvider(
418 	const uno::Reference< frame::XDispatchProvider >& NewSupplier )
419 	throw (
420 		uno::RuntimeException
421 	)
422 {
423 	osl::MutexGuard aGuard(m_aMutex);
424 	m_xMasterDispatchProvider = NewSupplier;
425 }
426 
427