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