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_embeddedobj.hxx"
26 #include <com/sun/star/frame/XFrame.hpp>
27 #include <com/sun/star/frame/XController.hpp>
28 #include <com/sun/star/frame/XComponentLoader.hpp>
29 #include <com/sun/star/awt/XTopWindow.hpp>
30 #include <com/sun/star/embed/XClassifiedObject.hpp>
31 #include <com/sun/star/io/XStream.hpp>
32 #include <com/sun/star/io/XInputStream.hpp>
33 #include <com/sun/star/io/XOutputStream.hpp>
34 #include <com/sun/star/io/XSeekable.hpp>
35 #include <com/sun/star/task/XInteractionHandler.hpp>
36 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
37 #include <com/sun/star/util/XCloseable.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 
40 #ifndef _COM_SUN_STAR_DOCUMENT_XEVENTBRODCASTER_HPP_
41 #include <com/sun/star/document/XEventBroadcaster.hpp>
42 #endif
43 #include <com/sun/star/document/XEventListener.hpp>
44 #include <com/sun/star/document/XTypeDetection.hpp>
45 #include <com/sun/star/container/XNameAccess.hpp>
46 #include <cppuhelper/implbase1.hxx>
47 #include <comphelper/storagehelper.hxx>
48 #include <comphelper/mimeconfighelper.hxx>
49 
50 #include "ownview.hxx"
51 
52 
53 using namespace ::com::sun::star;
54 using namespace ::comphelper;
55 
56 ::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException );
57 ::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException );
58 sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory );
59 uno::Reference< io::XStream > TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw ( uno::Exception );
60 
61 //========================================================
62 // Dummy interaction handler
63 //========================================================
64 //--------------------------------------------------------
65 class DummyHandler_Impl : public ::cppu::WeakImplHelper1< task::XInteractionHandler >
66 {
67 public:
DummyHandler_Impl()68 	DummyHandler_Impl() {}
69 	~DummyHandler_Impl();
70 
71 	virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& xRequest )
72 			throw( uno::RuntimeException );
73 };
74 
75 //--------------------------------------------------------
~DummyHandler_Impl()76 DummyHandler_Impl::~DummyHandler_Impl()
77 {
78 }
79 
80 //--------------------------------------------------------
handle(const uno::Reference<task::XInteractionRequest> &)81 void SAL_CALL DummyHandler_Impl::handle( const uno::Reference< task::XInteractionRequest >& )
82 		throw( uno::RuntimeException )
83 {
84 	return;
85 }
86 
87 //========================================================
88 // Object viewer
89 //========================================================
90 //--------------------------------------------------------
OwnView_Impl(const uno::Reference<lang::XMultiServiceFactory> & xFactory,const uno::Reference<io::XInputStream> & xInputStream)91 OwnView_Impl::OwnView_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory,
92 							const uno::Reference< io::XInputStream >& xInputStream )
93 : m_xFactory( xFactory )
94 , m_bBusy( sal_False )
95 , m_bUseNative( sal_False )
96 {
97 	if ( !xFactory.is() || !xInputStream.is() )
98 		throw uno::RuntimeException();
99 
100 	m_aTempFileURL = GetNewFilledTempFile_Impl( xInputStream, m_xFactory );
101 }
102 
103 //--------------------------------------------------------
~OwnView_Impl()104 OwnView_Impl::~OwnView_Impl()
105 {
106 	try {
107 		KillFile_Impl( m_aTempFileURL, m_xFactory );
108 	} catch( uno::Exception& ) {}
109 
110 	try {
111 		if ( m_aNativeTempURL.getLength() )
112 			KillFile_Impl( m_aNativeTempURL, m_xFactory );
113 	} catch( uno::Exception& ) {}
114 }
115 
116 //--------------------------------------------------------
CreateModelFromURL(const::rtl::OUString & aFileURL)117 sal_Bool OwnView_Impl::CreateModelFromURL( const ::rtl::OUString& aFileURL )
118 {
119 	sal_Bool bResult = sal_False;
120 
121 	if ( aFileURL.getLength() )
122 	{
123 		try {
124 			uno::Reference < frame::XComponentLoader > xDocumentLoader(
125 							m_xFactory->createInstance (
126 										::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ),
127 							uno::UNO_QUERY );
128 
129 			if ( xDocumentLoader.is() )
130 			{
131 				uno::Sequence< beans::PropertyValue > aArgs( m_aFilterName.getLength() ? 5 : 4 );
132 
133 				aArgs[0].Name = ::rtl::OUString::createFromAscii( "URL" );
134 				aArgs[0].Value <<= aFileURL;
135 
136 				aArgs[1].Name = ::rtl::OUString::createFromAscii( "ReadOnly" );
137 				aArgs[1].Value <<= sal_True;
138 
139 				aArgs[2].Name = ::rtl::OUString::createFromAscii( "InteractionHandler" );
140 				aArgs[2].Value <<= uno::Reference< task::XInteractionHandler >(
141 									static_cast< ::cppu::OWeakObject* >( new DummyHandler_Impl() ), uno::UNO_QUERY );
142 
143 				aArgs[3].Name = ::rtl::OUString::createFromAscii( "DontEdit" );
144 				aArgs[3].Value <<= sal_True;
145 
146 				if ( m_aFilterName.getLength() )
147 				{
148 					aArgs[4].Name = ::rtl::OUString::createFromAscii( "FilterName" );
149 					aArgs[4].Value <<= m_aFilterName;
150 				}
151 
152 				uno::Reference< frame::XModel > xModel( xDocumentLoader->loadComponentFromURL(
153 																aFileURL,
154 																::rtl::OUString::createFromAscii( "_blank" ),
155 																0,
156 																aArgs ),
157 															uno::UNO_QUERY );
158 
159 				if ( xModel.is() )
160 				{
161 					uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
162 					if ( xBroadCaster.is() )
163 						xBroadCaster->addEventListener( uno::Reference< document::XEventListener >(
164 																static_cast< ::cppu::OWeakObject* >( this ),
165 									 							uno::UNO_QUERY ) );
166 
167 					uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
168 					if ( xCloseable.is() )
169 					{
170 						xCloseable->addCloseListener( uno::Reference< util::XCloseListener >(
171 																		static_cast< ::cppu::OWeakObject* >( this ),
172 										  								uno::UNO_QUERY ) );
173 
174 						::osl::MutexGuard aGuard( m_aMutex );
175 						m_xModel = xModel;
176 						bResult = sal_True;
177 					}
178 				}
179 			}
180 		}
181 		catch( uno::Exception& )
182 		{
183 		}
184 	}
185 
186 	return bResult;
187 }
188 
189 //--------------------------------------------------------
CreateModel(sal_Bool bUseNative)190 sal_Bool OwnView_Impl::CreateModel( sal_Bool bUseNative )
191 {
192 	sal_Bool bResult = sal_False;
193 
194 	try {
195 		bResult = CreateModelFromURL( bUseNative ? m_aNativeTempURL : m_aTempFileURL );
196 	}
197 	catch( uno::Exception& )
198 	{
199 	}
200 
201 	return bResult;
202 }
203 
204 //--------------------------------------------------------
GetFilterNameFromExtentionAndInStream(const::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & xFactory,const::rtl::OUString & aNameWithExtention,const uno::Reference<io::XInputStream> & xInputStream)205 ::rtl::OUString OwnView_Impl::GetFilterNameFromExtentionAndInStream(
206                                                     const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory,
207                                                     const ::rtl::OUString& aNameWithExtention,
208                                                     const uno::Reference< io::XInputStream >& xInputStream )
209 {
210 	if ( !xInputStream.is() )
211 		throw uno::RuntimeException();
212 
213 	uno::Reference< document::XTypeDetection > xTypeDetection(
214 			xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ),
215 			uno::UNO_QUERY_THROW );
216 
217 	::rtl::OUString aTypeName;
218 
219 	if ( aNameWithExtention.getLength() )
220 	{
221 		::rtl::OUString aURLToAnalyze =
222 				( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "file:///" ) ) + aNameWithExtention );
223 		aTypeName = xTypeDetection->queryTypeByURL( aURLToAnalyze );
224 	}
225 
226 	uno::Sequence< beans::PropertyValue > aArgs( aTypeName.getLength() ? 3 : 2 );
227 	aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
228 	aArgs[0].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" ) );
229 	aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) );
230 	aArgs[1].Value <<= xInputStream;
231 	if ( aTypeName.getLength() )
232 	{
233 		aArgs[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TypeName" ) );
234 		aArgs[2].Value <<= aTypeName;
235 	}
236 
237 	aTypeName = xTypeDetection->queryTypeByDescriptor( aArgs, sal_True );
238 
239 	::rtl::OUString aFilterName;
240 	for ( sal_Int32 nInd = 0; nInd < aArgs.getLength(); nInd++ )
241 		if ( aArgs[nInd].Name.equalsAscii( "FilterName" ) )
242 			aArgs[nInd].Value >>= aFilterName;
243 
244 	if ( !aFilterName.getLength() && aTypeName.getLength() )
245 	{
246 		// get the default filter name for the type
247 		uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY_THROW );
248 		uno::Sequence< beans::PropertyValue > aTypes;
249 
250 		if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) )
251 		{
252 			for ( sal_Int32 nInd = 0; nInd < aTypes.getLength(); nInd++ )
253 			{
254 				if ( aTypes[nInd].Name.equalsAscii( "PreferredFilter" ) && ( aTypes[nInd].Value >>= aFilterName ) )
255 				{
256 					aTypes[nInd].Value >>= aFilterName;
257 					break;
258 				}
259 			}
260 		}
261 	}
262 
263 	return aFilterName;
264 }
265 
266 //--------------------------------------------------------
ReadContentsAndGenerateTempFile(const uno::Reference<io::XInputStream> & xInStream,sal_Bool bParseHeader)267 sal_Bool OwnView_Impl::ReadContentsAndGenerateTempFile( const uno::Reference< io::XInputStream >& xInStream,
268 														sal_Bool bParseHeader )
269 {
270 	uno::Reference< io::XSeekable > xSeekable( xInStream, uno::UNO_QUERY_THROW );
271 	xSeekable->seek( 0 );
272 
273 	// create m_aNativeTempURL
274 	::rtl::OUString aNativeTempURL;
275 	uno::Reference < beans::XPropertySet > xNativeTempFile(
276 			m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
277 			uno::UNO_QUERY_THROW );
278 	uno::Reference < io::XStream > xNativeTempStream( xNativeTempFile, uno::UNO_QUERY_THROW );
279 	uno::Reference < io::XOutputStream > xNativeOutTemp = xNativeTempStream->getOutputStream();
280 	uno::Reference < io::XInputStream > xNativeInTemp = xNativeTempStream->getInputStream();
281 	if ( !xNativeOutTemp.is() || !xNativeInTemp.is() )
282 		throw uno::RuntimeException();
283 
284 	try {
285 		xNativeTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
286 		uno::Any aUrl = xNativeTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
287 		aUrl >>= aNativeTempURL;
288 	}
289 	catch ( uno::Exception& )
290 	{
291 	}
292 
293 	sal_Bool bFailed = sal_False;
294 	::rtl::OUString aFileSuffix;
295 
296 	if ( bParseHeader )
297 	{
298 		uno::Sequence< sal_Int8 > aReadSeq( 4 );
299 		// read the complete size of the Object Package
300 		if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
301 			return sal_False;
302 /*
303 		sal_uInt32 nLength = (sal_uInt8)aReadSeq[0]
304 							+ (sal_uInt8)aReadSeq[1] * 0x100
305 							+ (sal_uInt8)aReadSeq[2] * 0x10000
306 							+ (sal_uInt8)aReadSeq[3] * 0x1000000;
307 */
308 		// read the first header ( have no idea what does this header mean )
309 		if ( xInStream->readBytes( aReadSeq, 2 ) != 2 || aReadSeq[0] != 2 || aReadSeq[1] != 0 )
310 			return sal_False;
311 
312 		// read file name
313 		// only extension is interesting so only subset of symbols is accepted
314 		do
315 		{
316 			if ( xInStream->readBytes( aReadSeq, 1 ) != 1 )
317 				return sal_False;
318 
319 			if (
320                 (aReadSeq[0] >= '0' && aReadSeq[0] <= '9') ||
321                 (aReadSeq[0] >= 'a' && aReadSeq[0] <= 'z') ||
322                 (aReadSeq[0] >= 'A' && aReadSeq[0] <= 'Z') ||
323                 aReadSeq[0] == '.'
324                )
325             {
326 				aFileSuffix += ::rtl::OUString::valueOf( (sal_Unicode) aReadSeq[0] );
327             }
328 
329 		} while( aReadSeq[0] );
330 
331 		// skip url
332 		do
333 		{
334 			if ( xInStream->readBytes( aReadSeq, 1 ) != 1 )
335 				return sal_False;
336 		} while( aReadSeq[0] );
337 
338 		// check the next header
339 		if ( xInStream->readBytes( aReadSeq, 4 ) != 4
340 	  	|| aReadSeq[0] || aReadSeq[1] || aReadSeq[2] != 3 || aReadSeq[3] )
341 			return sal_False;
342 
343 		// get the size of the next entry
344 		if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
345 			return sal_False;
346 
347 		sal_uInt32 nUrlSize = (sal_uInt8)aReadSeq[0]
348 							+ (sal_uInt8)aReadSeq[1] * 0x100
349 							+ (sal_uInt8)aReadSeq[2] * 0x10000
350 							+ (sal_uInt8)aReadSeq[3] * 0x1000000;
351 		sal_Int64 nTargetPos = xSeekable->getPosition() + nUrlSize;
352 
353 		xSeekable->seek( nTargetPos );
354 
355 		// get the size of stored data
356 		if ( xInStream->readBytes( aReadSeq, 4 ) != 4 )
357 			return sal_False;
358 
359 		sal_uInt32 nDataSize = (sal_uInt8)aReadSeq[0]
360 							+ (sal_uInt8)aReadSeq[1] * 0x100
361 							+ (sal_uInt8)aReadSeq[2] * 0x10000
362 							+ (sal_uInt8)aReadSeq[3] * 0x1000000;
363 
364 		aReadSeq.realloc( 32000 );
365 		sal_uInt32 nRead = 0;
366 		while ( nRead < nDataSize )
367 		{
368 			sal_uInt32 nToRead = ( nDataSize - nRead > 32000 ) ? 32000 : nDataSize - nRead;
369 			sal_uInt32 nLocalRead = xInStream->readBytes( aReadSeq, nToRead );
370 
371 
372 			if ( !nLocalRead )
373 			{
374 				bFailed = sal_True;
375 				break;
376 			}
377 			else if ( nLocalRead == 32000 )
378 				xNativeOutTemp->writeBytes( aReadSeq );
379 			else
380 			{
381 				uno::Sequence< sal_Int8 > aToWrite( aReadSeq );
382 				aToWrite.realloc( nLocalRead );
383 				xNativeOutTemp->writeBytes( aToWrite );
384 			}
385 
386 			nRead += nLocalRead;
387 		}
388 	}
389 	else
390 	{
391 		uno::Sequence< sal_Int8 > aData( 8 );
392 		if ( xInStream->readBytes( aData, 8 ) == 8
393 		  && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1
394 		  && ( aData[4] == 2 || aData[4] == 3 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
395 		{
396 			// the header has to be removed
397 			xSeekable->seek( 40 );
398 		}
399 		else
400 		{
401 			// the usual Ole10Native format
402 			xSeekable->seek( 4 );
403 		}
404 
405 		::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xNativeOutTemp );
406 	}
407 
408 	xNativeOutTemp->closeOutput();
409 
410 	// The temporary native file is created, now the filter must be detected
411 	if ( !bFailed )
412 	{
413 		m_aFilterName = GetFilterNameFromExtentionAndInStream( m_xFactory, aFileSuffix, xNativeInTemp );
414 		m_aNativeTempURL = aNativeTempURL;
415 	}
416 
417 	return !bFailed;
418 }
419 
420 //--------------------------------------------------------
CreateNative()421 void OwnView_Impl::CreateNative()
422 {
423 	if ( m_aNativeTempURL.getLength() )
424 		return;
425 
426 	try
427 	{
428 		uno::Reference < ucb::XSimpleFileAccess > xAccess(
429 				m_xFactory->createInstance (
430 						::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
431 				uno::UNO_QUERY_THROW );
432 
433 		uno::Reference< io::XInputStream > xInStream = xAccess->openFileRead( m_aTempFileURL );
434 		if ( !xInStream.is() )
435 			throw uno::RuntimeException();
436 
437 		uno::Sequence< uno::Any > aArgs( 1 );
438 		aArgs[0] <<= xInStream;
439 		uno::Reference< container::XNameAccess > xNameAccess(
440 				m_xFactory->createInstanceWithArguments(
441 						::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ),
442 						aArgs ),
443 				uno::UNO_QUERY_THROW );
444 
445 		::rtl::OUString aSubStreamName = ::rtl::OUString::createFromAscii( "\1Ole10Native" );
446 		uno::Reference< embed::XClassifiedObject > xStor( xNameAccess, uno::UNO_QUERY_THROW );
447 		uno::Sequence< sal_Int8 > aStorClassID = xStor->getClassID();
448 
449 		if ( xNameAccess->hasByName( aSubStreamName ) )
450 		{
451 			sal_uInt8 aClassID[] =
452 				{ 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
453 			uno::Sequence< sal_Int8 > aPackageClassID( (sal_Int8*)aClassID, 16 );
454 
455 			uno::Reference< io::XStream > xSubStream;
456 			xNameAccess->getByName( aSubStreamName ) >>= xSubStream;
457 			if ( xSubStream.is() )
458 			{
459 				sal_Bool bOk = sal_False;
460 
461 				if ( MimeConfigurationHelper::ClassIDsEqual( aPackageClassID, aStorClassID ) )
462 				{
463 					// the storage represents Object Package
464 
465 					bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), sal_True );
466 
467 					if ( !bOk && m_aNativeTempURL.getLength() )
468 					{
469 						KillFile_Impl( m_aNativeTempURL, m_xFactory );
470 						m_aNativeTempURL = ::rtl::OUString();
471 					}
472 				}
473 
474 				if ( !bOk )
475 				{
476 					bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), sal_False );
477 
478 					if ( !bOk && m_aNativeTempURL.getLength() )
479 					{
480 						KillFile_Impl( m_aNativeTempURL, m_xFactory );
481 						m_aNativeTempURL = ::rtl::OUString();
482 					}
483 				}
484 			}
485 		}
486 		else
487 		{
488 			// TODO/LATER: No native stream, needs a new solution
489 		}
490 	}
491 	catch( uno::Exception& )
492 	{}
493 }
494 
495 //--------------------------------------------------------
Open()496 sal_Bool OwnView_Impl::Open()
497 {
498 	sal_Bool bResult = sal_False;
499 
500 	uno::Reference< frame::XModel > xExistingModel;
501 
502 	{
503 		::osl::MutexGuard aGuard( m_aMutex );
504 		xExistingModel = m_xModel;
505 		if ( m_bBusy )
506 			return sal_False;
507 
508 		m_bBusy = sal_True;
509 	}
510 
511 	if ( xExistingModel.is() )
512 	{
513 		try {
514 			uno::Reference< frame::XController > xController = xExistingModel->getCurrentController();
515 			if ( xController.is() )
516 			{
517 				uno::Reference< frame::XFrame > xFrame = xController->getFrame();
518 				if ( xFrame.is() )
519 				{
520 					xFrame->activate();
521 					uno::Reference<awt::XTopWindow> xTopWindow( xFrame->getContainerWindow(), uno::UNO_QUERY );
522 					if(xTopWindow.is())
523 						xTopWindow->toFront();
524 
525 					bResult = sal_True;
526 				}
527 			}
528 		}
529 		catch( uno::Exception& )
530 		{
531 		}
532 	}
533 	else
534 	{
535 		bResult = CreateModel( m_bUseNative );
536 
537 		if ( !bResult && !m_bUseNative )
538 		{
539 			// the original storage can not be recognized
540 			if ( !m_aNativeTempURL.getLength() )
541 			{
542 				// create a temporary file for the native representation if there is no
543 				CreateNative();
544 			}
545 
546 			if ( m_aNativeTempURL.getLength() )
547 			{
548 				bResult = CreateModel( sal_True );
549 				if ( bResult )
550 					m_bUseNative = sal_True;
551 			}
552 		}
553 	}
554 
555 	m_bBusy = sal_False;
556 
557 	return bResult;
558 }
559 
560 //--------------------------------------------------------
Close()561 void OwnView_Impl::Close()
562 {
563 	uno::Reference< frame::XModel > xModel;
564 
565 	{
566 		::osl::MutexGuard aGuard( m_aMutex );
567 		if ( !m_xModel.is() )
568 			return;
569 		xModel = m_xModel;
570 		m_xModel = uno::Reference< frame::XModel >();
571 
572 		if ( m_bBusy )
573 			return;
574 
575 		m_bBusy = sal_True;
576 	}
577 
578 	try {
579 		uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
580 		if ( xBroadCaster.is() )
581 			xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >(
582 																	static_cast< ::cppu::OWeakObject* >( this ),
583 											 						uno::UNO_QUERY ) );
584 
585 		uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
586 		if ( xCloseable.is() )
587 		{
588 			xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >(
589 																	static_cast< ::cppu::OWeakObject* >( this ),
590 											 						uno::UNO_QUERY ) );
591 			xCloseable->close( sal_True );
592 		}
593 	}
594 	catch( uno::Exception& )
595 	{}
596 
597 	m_bBusy = sal_False;
598 }
599 
600 //--------------------------------------------------------
notifyEvent(const document::EventObject & aEvent)601 void SAL_CALL OwnView_Impl::notifyEvent( const document::EventObject& aEvent )
602 		throw ( uno::RuntimeException )
603 {
604 
605 	uno::Reference< frame::XModel > xModel;
606 
607 	{
608 		::osl::MutexGuard aGuard( m_aMutex );
609 		if ( aEvent.Source == m_xModel && aEvent.EventName.equalsAscii( "OnSaveAsDone" ) )
610 		{
611 			// SaveAs operation took place, so just forget the model and deregister listeners
612 			xModel = m_xModel;
613 			m_xModel = uno::Reference< frame::XModel >();
614 		}
615 	}
616 
617 	if ( xModel.is() )
618 	{
619 		try {
620 			uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY );
621 			if ( xBroadCaster.is() )
622 				xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >(
623 																		static_cast< ::cppu::OWeakObject* >( this ),
624 											 							uno::UNO_QUERY ) );
625 
626 			uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
627 			if ( xCloseable.is() )
628 				xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >(
629 																		static_cast< ::cppu::OWeakObject* >( this ),
630 											 							uno::UNO_QUERY ) );
631 		}
632 		catch( uno::Exception& )
633 		{}
634 	}
635 }
636 
637 //--------------------------------------------------------
queryClosing(const lang::EventObject &,sal_Bool)638 void SAL_CALL OwnView_Impl::queryClosing( const lang::EventObject&, sal_Bool )
639 		throw ( util::CloseVetoException,
640 				uno::RuntimeException )
641 {
642 }
643 
644 //--------------------------------------------------------
notifyClosing(const lang::EventObject & Source)645 void SAL_CALL OwnView_Impl::notifyClosing( const lang::EventObject& Source )
646 		throw ( uno::RuntimeException )
647 {
648 	::osl::MutexGuard aGuard( m_aMutex );
649 	if ( Source.Source == m_xModel )
650 		m_xModel = uno::Reference< frame::XModel >();
651 }
652 
653 //--------------------------------------------------------
disposing(const lang::EventObject & Source)654 void SAL_CALL OwnView_Impl::disposing( const lang::EventObject& Source )
655 		throw (uno::RuntimeException)
656 {
657 	::osl::MutexGuard aGuard( m_aMutex );
658 	if ( Source.Source == m_xModel )
659 		m_xModel = uno::Reference< frame::XModel >();
660 };
661 
662