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