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 
31 #include <commonembobj.hxx>
32 #include <com/sun/star/embed/EmbedStates.hpp>
33 #include <com/sun/star/embed/EmbedVerbs.hpp>
34 #include <com/sun/star/embed/XStorage.hpp>
35 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
36 #include <com/sun/star/embed/XInplaceClient.hpp>
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include <com/sun/star/beans/NamedValue.hpp>
39 
40 #include <cppuhelper/typeprovider.hxx>
41 #include <cppuhelper/interfacecontainer.h>
42 #include <comphelper/mimeconfighelper.hxx>
43 
44 #include "closepreventer.hxx"
45 #include "intercept.hxx"
46 
47 using namespace ::com::sun::star;
48 
49 
50 uno::Sequence< beans::PropertyValue > GetValuableArgs_Impl( const uno::Sequence< beans::PropertyValue >& aMedDescr,
51                                                             sal_Bool bCanUseDocumentBaseURL );
52 
53 //------------------------------------------------------
54 OCommonEmbeddedObject::OCommonEmbeddedObject( const uno::Reference< lang::XMultiServiceFactory >& xFactory,
55                                                 const uno::Sequence< beans::NamedValue >& aObjProps )
56 : m_pDocHolder( NULL )
57 , m_pInterfaceContainer( NULL )
58 , m_bReadOnly( sal_False )
59 , m_bDisposed( sal_False )
60 , m_bClosed( sal_False )
61 , m_nObjectState( -1 )
62 , m_nTargetState( -1 )
63 , m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE )
64 , m_xFactory( xFactory )
65 , m_nMiscStatus( 0 )
66 , m_bEmbeddedScriptSupport( sal_True )
67 , m_bDocumentRecoverySupport( sal_True )
68 , m_bWaitSaveCompleted( sal_False )
69 , m_bIsLink( sal_False )
70 , m_bLinkHasPassword( sal_False )
71 , m_bHasClonedSize( sal_False )
72 , m_nClonedMapUnit( 0 )
73 {
74     CommonInit_Impl( aObjProps );
75 }
76 
77 //------------------------------------------------------
78 OCommonEmbeddedObject::OCommonEmbeddedObject(
79         const uno::Reference< lang::XMultiServiceFactory >& xFactory,
80         const uno::Sequence< beans::NamedValue >& aObjProps,
81         const uno::Sequence< beans::PropertyValue >& aMediaDescr,
82         const uno::Sequence< beans::PropertyValue >& aObjectDescr )
83 : m_pDocHolder( NULL )
84 , m_pInterfaceContainer( NULL )
85 , m_bReadOnly( sal_False )
86 , m_bDisposed( sal_False )
87 , m_bClosed( sal_False )
88 , m_nObjectState( embed::EmbedStates::LOADED )
89 , m_nTargetState( -1 )
90 , m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE )
91 , m_xFactory( xFactory )
92 , m_nMiscStatus( 0 )
93 , m_bEmbeddedScriptSupport( sal_True )
94 , m_bDocumentRecoverySupport( sal_True )
95 , m_bWaitSaveCompleted( sal_False )
96 , m_bIsLink( sal_True )
97 , m_bLinkHasPassword( sal_False )
98 , m_bHasClonedSize( sal_False )
99 , m_nClonedMapUnit( 0 )
100 {
101     // linked object has no own persistence so it is in loaded state starting from creation
102     LinkInit_Impl( aObjProps, aMediaDescr, aObjectDescr );
103 }
104 
105 //------------------------------------------------------
106 void OCommonEmbeddedObject::CommonInit_Impl( const uno::Sequence< beans::NamedValue >& aObjectProps )
107 {
108     OSL_ENSURE( m_xFactory.is(), "No ServiceFactory is provided!\n" );
109     if ( !m_xFactory.is() )
110         throw uno::RuntimeException();
111 
112     m_pDocHolder = new DocumentHolder( m_xFactory, this );
113     m_pDocHolder->acquire();
114 
115     // parse configuration entries
116     // TODO/LATER: in future UI names can be also provided here
117     for ( sal_Int32 nInd = 0; nInd < aObjectProps.getLength(); nInd++ )
118     {
119         if ( aObjectProps[nInd].Name.equalsAscii( "ClassID" ) )
120             aObjectProps[nInd].Value >>= m_aClassID;
121         else if ( aObjectProps[nInd].Name.equalsAscii( "ObjectDocumentServiceName" ) )
122             aObjectProps[nInd].Value >>= m_aDocServiceName;
123         else if ( aObjectProps[nInd].Name.equalsAscii( "ObjectDocumentFilterName" ) )
124             aObjectProps[nInd].Value >>= m_aPresetFilterName;
125         else if ( aObjectProps[nInd].Name.equalsAscii( "ObjectMiscStatus" ) )
126             aObjectProps[nInd].Value >>= m_nMiscStatus;
127         else if ( aObjectProps[nInd].Name.equalsAscii( "ObjectVerbs" ) )
128             aObjectProps[nInd].Value >>= m_aObjectVerbs;
129     }
130 
131     if ( m_aClassID.getLength() != 16 /*|| !m_aDocServiceName.getLength()*/ )
132         throw uno::RuntimeException(); // something goes really wrong
133 
134     // accepted states
135     m_aAcceptedStates.realloc( NUM_SUPPORTED_STATES );
136 
137     m_aAcceptedStates[0] = embed::EmbedStates::LOADED;
138     m_aAcceptedStates[1] = embed::EmbedStates::RUNNING;
139     m_aAcceptedStates[2] = embed::EmbedStates::INPLACE_ACTIVE;
140     m_aAcceptedStates[3] = embed::EmbedStates::UI_ACTIVE;
141     m_aAcceptedStates[4] = embed::EmbedStates::ACTIVE;
142 
143 
144     // intermediate states
145     // In the following table the first index points to starting state,
146     // the second one to the target state, and the sequence referenced by
147     // first two indexes contains intermediate states, that should be
148     // passed by object to reach the target state.
149     // If the sequence is empty that means that indirect switch from start
150     // state to the target state is forbidden, only if direct switch is possible
151     // the state can be reached.
152 
153     m_pIntermediateStatesSeqs[0][2].realloc( 1 );
154     m_pIntermediateStatesSeqs[0][2][0] = embed::EmbedStates::RUNNING;
155 
156     m_pIntermediateStatesSeqs[0][3].realloc( 2 );
157     m_pIntermediateStatesSeqs[0][3][0] = embed::EmbedStates::RUNNING;
158     m_pIntermediateStatesSeqs[0][3][1] = embed::EmbedStates::INPLACE_ACTIVE;
159 
160     m_pIntermediateStatesSeqs[0][4].realloc( 1 );
161     m_pIntermediateStatesSeqs[0][4][0] = embed::EmbedStates::RUNNING;
162 
163     m_pIntermediateStatesSeqs[1][3].realloc( 1 );
164     m_pIntermediateStatesSeqs[1][3][0] = embed::EmbedStates::INPLACE_ACTIVE;
165 
166     m_pIntermediateStatesSeqs[2][0].realloc( 1 );
167     m_pIntermediateStatesSeqs[2][0][0] = embed::EmbedStates::RUNNING;
168 
169     m_pIntermediateStatesSeqs[3][0].realloc( 2 );
170     m_pIntermediateStatesSeqs[3][0][0] = embed::EmbedStates::INPLACE_ACTIVE;
171     m_pIntermediateStatesSeqs[3][0][1] = embed::EmbedStates::RUNNING;
172 
173     m_pIntermediateStatesSeqs[3][1].realloc( 1 );
174     m_pIntermediateStatesSeqs[3][1][0] = embed::EmbedStates::INPLACE_ACTIVE;
175 
176     m_pIntermediateStatesSeqs[4][0].realloc( 1 );
177     m_pIntermediateStatesSeqs[4][0][0] = embed::EmbedStates::RUNNING;
178 
179     // verbs table
180     sal_Int32 nVerbTableSize = 0;
181     for ( sal_Int32 nVerbInd = 0; nVerbInd < m_aObjectVerbs.getLength(); nVerbInd++ )
182     {
183         if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_PRIMARY )
184         {
185             m_aVerbTable.realloc( ++nVerbTableSize );
186             m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
187             m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
188             m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::UI_ACTIVE;
189         }
190         else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_SHOW )
191         {
192             m_aVerbTable.realloc( ++nVerbTableSize );
193             m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
194             m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
195             m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::UI_ACTIVE;
196         }
197         else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_OPEN )
198         {
199             m_aVerbTable.realloc( ++nVerbTableSize );
200             m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
201             m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
202             m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::ACTIVE;
203         }
204         else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE )
205         {
206             m_aVerbTable.realloc( ++nVerbTableSize );
207             m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
208             m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
209             m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::INPLACE_ACTIVE;
210         }
211         else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE )
212         {
213             m_aVerbTable.realloc( ++nVerbTableSize );
214             m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
215             m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
216             m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::UI_ACTIVE;
217         }
218         else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_HIDE )
219         {
220             m_aVerbTable.realloc( ++nVerbTableSize );
221             m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
222             m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
223             m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::RUNNING;
224         }
225     }
226 }
227 
228 //------------------------------------------------------
229 void OCommonEmbeddedObject::LinkInit_Impl(
230                                 const uno::Sequence< beans::NamedValue >& aObjectProps,
231                                 const uno::Sequence< beans::PropertyValue >& aMediaDescr,
232                                 const uno::Sequence< beans::PropertyValue >& aObjectDescr )
233 {
234     // setPersistance has no effect on own links, so the complete initialization must be done here
235 
236     for ( sal_Int32 nInd = 0; nInd < aMediaDescr.getLength(); nInd++ )
237         if ( aMediaDescr[nInd].Name.equalsAscii( "URL" ) )
238             aMediaDescr[nInd].Value >>= m_aLinkURL;
239         else if ( aMediaDescr[nInd].Name.equalsAscii( "FilterName" ) )
240             aMediaDescr[nInd].Value >>= m_aLinkFilterName;
241 
242     OSL_ENSURE( m_aLinkURL.getLength() && m_aLinkFilterName.getLength(), "Filter and URL must be provided!\n" );
243 
244     m_bReadOnly = sal_True;
245     if ( m_aLinkFilterName.getLength() )
246     {
247         ::comphelper::MimeConfigurationHelper aHelper( m_xFactory );
248         ::rtl::OUString aExportFilterName = aHelper.GetExportFilterFromImportFilter( m_aLinkFilterName );
249         m_bReadOnly = !( aExportFilterName.equals( m_aLinkFilterName ) );
250     }
251 
252     m_aDocMediaDescriptor = GetValuableArgs_Impl( aMediaDescr, sal_False );
253 
254     uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
255     for ( sal_Int32 nObjInd = 0; nObjInd < aObjectDescr.getLength(); nObjInd++ )
256         if ( aObjectDescr[nObjInd].Name.equalsAscii( "OutplaceDispatchInterceptor" ) )
257         {
258             aObjectDescr[nObjInd].Value >>= xDispatchInterceptor;
259             break;
260         }
261         else if ( aObjectDescr[nObjInd].Name.equalsAscii( "Parent" ) )
262         {
263             aObjectDescr[nObjInd].Value >>= m_xParent;
264         }
265 
266     CommonInit_Impl( aObjectProps );
267 
268     if ( xDispatchInterceptor.is() )
269         m_pDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
270 }
271 
272 //------------------------------------------------------
273 OCommonEmbeddedObject::~OCommonEmbeddedObject()
274 {
275     if ( m_pInterfaceContainer || m_pDocHolder )
276     {
277         m_refCount++;
278         try {
279             lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
280 
281             if ( m_pInterfaceContainer )
282             {
283                 m_pInterfaceContainer->disposeAndClear( aSource );
284 
285                 delete m_pInterfaceContainer;
286                 m_pInterfaceContainer = NULL;
287             }
288         } catch( uno::Exception& ) {}
289 
290         try {
291             if ( m_pDocHolder )
292             {
293                 m_pDocHolder->CloseFrame();
294                 try {
295                     m_pDocHolder->CloseDocument( sal_True, sal_True );
296                 } catch ( uno::Exception& ) {}
297                 m_pDocHolder->FreeOffice();
298 
299                 m_pDocHolder->release();
300                 m_pDocHolder = NULL;
301             }
302         } catch( uno::Exception& ) {}
303     }
304 }
305 
306 //------------------------------------------------------
307 void OCommonEmbeddedObject::requestPositioning( const awt::Rectangle& aRect )
308 {
309     // the method is called in case object is inplace active and the object window was resized
310 
311     OSL_ENSURE( m_xClientSite.is(), "The client site must be set for inplace active object!\n" );
312     if ( m_xClientSite.is() )
313     {
314         uno::Reference< embed::XInplaceClient > xInplaceClient( m_xClientSite, uno::UNO_QUERY );
315 
316         OSL_ENSURE( xInplaceClient.is(), "The client site must support XInplaceClient to allow inplace activation!\n" );
317         if ( xInplaceClient.is() )
318         {
319             try {
320                 xInplaceClient->changedPlacement( aRect );
321             }
322             catch( uno::Exception& )
323             {
324                 OSL_ENSURE( sal_False, "Exception on request to resize!\n" );
325             }
326         }
327     }
328 }
329 
330 //------------------------------------------------------
331 void OCommonEmbeddedObject::PostEvent_Impl( const ::rtl::OUString& aEventName,
332                                             const uno::Reference< uno::XInterface >& /*xSource*/ )
333 {
334     if ( m_pInterfaceContainer )
335     {
336         ::cppu::OInterfaceContainerHelper* pIC = m_pInterfaceContainer->getContainer(
337                                             ::getCppuType((const uno::Reference< document::XEventListener >*)0) );
338         if( pIC )
339         {
340             document::EventObject aEvent;
341             aEvent.EventName = aEventName;
342             aEvent.Source = uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) );
343             // For now all the events are sent as object events
344             // aEvent.Source = ( xSource.is() ? xSource
345             //                       : uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ) );
346             ::cppu::OInterfaceIteratorHelper aIt( *pIC );
347             while( aIt.hasMoreElements() )
348             {
349                 try
350                 {
351                     ((document::XEventListener *)aIt.next())->notifyEvent( aEvent );
352                 }
353                 catch( uno::RuntimeException& )
354                 {
355                     aIt.remove();
356                 }
357 
358                 // the listener could dispose the object.
359                 if ( m_bDisposed )
360                     return;
361             }
362         }
363     }
364 }
365 
366 //------------------------------------------------------
367 uno::Any SAL_CALL OCommonEmbeddedObject::queryInterface( const uno::Type& rType )
368         throw( uno::RuntimeException )
369 {
370     uno::Any aReturn;
371 
372     if ( rType == ::getCppuType( (uno::Reference< embed::XEmbeddedObject > const *)0 ))
373     {
374         void * p = static_cast< embed::XEmbeddedObject * >( this );
375         return uno::Any( &p, rType );
376     }
377     else
378         aReturn <<= ::cppu::queryInterface(
379                     rType,
380                     static_cast< embed::XInplaceObject* >( this ),
381                     static_cast< embed::XVisualObject* >( this ),
382                     static_cast< embed::XCommonEmbedPersist* >( static_cast< embed::XEmbedPersist* >( this ) ),
383                     static_cast< embed::XEmbedPersist* >( this ),
384                     static_cast< embed::XLinkageSupport* >( this ),
385                     static_cast< embed::XStateChangeBroadcaster* >( this ),
386                     static_cast< embed::XClassifiedObject* >( this ),
387                     static_cast< embed::XComponentSupplier* >( this ),
388                     static_cast< util::XCloseable* >( this ),
389                     static_cast< container::XChild* >( this ),
390                     static_cast< chart2::XDefaultSizeTransmitter* >( this ),
391                     static_cast< document::XEventBroadcaster* >( this ) );
392 
393     if ( aReturn.hasValue() )
394         return aReturn;
395     else
396         return ::cppu::OWeakObject::queryInterface( rType ) ;
397 
398 }
399 
400 //------------------------------------------------------
401 void SAL_CALL OCommonEmbeddedObject::acquire()
402         throw()
403 {
404     ::cppu::OWeakObject::acquire() ;
405 }
406 
407 //------------------------------------------------------
408 void SAL_CALL OCommonEmbeddedObject::release()
409         throw()
410 {
411     ::cppu::OWeakObject::release() ;
412 }
413 
414 //------------------------------------------------------
415 uno::Sequence< uno::Type > SAL_CALL OCommonEmbeddedObject::getTypes()
416         throw( uno::RuntimeException )
417 {
418     static ::cppu::OTypeCollection* pTypeCollection = NULL;
419 
420     if ( !pTypeCollection )
421     {
422         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
423         if ( !pTypeCollection )
424         {
425             if ( m_bIsLink )
426             {
427                 static ::cppu::OTypeCollection aTypeCollection(
428                                             ::getCppuType( (const uno::Reference< lang::XTypeProvider >*)NULL ),
429                                             ::getCppuType( (const uno::Reference< embed::XEmbeddedObject >*)NULL ),
430                                             ::getCppuType( (const uno::Reference< embed::XInplaceObject >*)NULL ),
431                                             ::getCppuType( (const uno::Reference< embed::XCommonEmbedPersist >*)NULL ),
432                                             ::getCppuType( (const uno::Reference< container::XChild >*)NULL ),
433                                             ::getCppuType( (const uno::Reference< embed::XLinkageSupport >*)NULL ) );
434 
435                 pTypeCollection = &aTypeCollection ;
436             }
437             else
438             {
439                    static ::cppu::OTypeCollection aTypeCollection(
440                                             ::getCppuType( (const uno::Reference< lang::XTypeProvider >*)NULL ),
441                                             ::getCppuType( (const uno::Reference< embed::XEmbeddedObject >*)NULL ),
442                                             ::getCppuType( (const uno::Reference< embed::XInplaceObject >*)NULL ),
443                                             ::getCppuType( (const uno::Reference< embed::XCommonEmbedPersist >*)NULL ),
444                                             ::getCppuType( (const uno::Reference< container::XChild >*)NULL ),
445                                             ::getCppuType( (const uno::Reference< embed::XEmbedPersist >*)NULL ) );
446 
447                 pTypeCollection = &aTypeCollection ;
448             }
449         }
450     }
451 
452     return pTypeCollection->getTypes() ;
453 
454 }
455 
456 //------------------------------------------------------
457 uno::Sequence< sal_Int8 > SAL_CALL OCommonEmbeddedObject::getImplementationId()
458         throw( uno::RuntimeException )
459 {
460     static ::cppu::OImplementationId* pID = NULL ;
461 
462     if ( !pID )
463     {
464         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;
465         if ( !pID )
466         {
467             static ::cppu::OImplementationId aID( sal_False ) ;
468             pID = &aID ;
469         }
470     }
471 
472     return pID->getImplementationId() ;
473 }
474 
475 //------------------------------------------------------
476 uno::Sequence< sal_Int8 > SAL_CALL OCommonEmbeddedObject::getClassID()
477         throw ( uno::RuntimeException )
478 {
479     if ( m_bDisposed )
480         throw lang::DisposedException();
481 
482     return m_aClassID;
483 }
484 
485 //------------------------------------------------------
486 ::rtl::OUString SAL_CALL OCommonEmbeddedObject::getClassName()
487         throw ( uno::RuntimeException )
488 {
489     if ( m_bDisposed )
490         throw lang::DisposedException();
491 
492     return m_aClassName;
493 }
494 
495 //------------------------------------------------------
496 void SAL_CALL OCommonEmbeddedObject::setClassInfo(
497                 const uno::Sequence< sal_Int8 >& /*aClassID*/, const ::rtl::OUString& /*aClassName*/ )
498         throw ( lang::NoSupportException,
499                 uno::RuntimeException )
500 {
501     // the object class info can not be changed explicitly
502     throw lang::NoSupportException(); //TODO:
503 }
504 
505 //------------------------------------------------------
506 uno::Reference< util::XCloseable > SAL_CALL OCommonEmbeddedObject::getComponent()
507         throw ( uno::RuntimeException )
508 {
509     ::osl::MutexGuard aGuard( m_aMutex );
510     if ( m_bDisposed )
511         throw lang::DisposedException(); // TODO
512 
513     // add an exception
514     if ( m_nObjectState == -1 )
515     {
516         // the object is still not loaded
517         throw uno::RuntimeException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ),
518                                         uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) );
519     }
520 
521     // if ( m_bWaitSaveCompleted )
522     //     throw embed::WrongStateException(
523     //                 ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ),
524     //                 uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) );
525 
526     return uno::Reference< util::XCloseable >( m_pDocHolder->GetComponent(), uno::UNO_QUERY );
527 }
528 
529 //----------------------------------------------
530 void SAL_CALL OCommonEmbeddedObject::addStateChangeListener( const uno::Reference< embed::XStateChangeListener >& xListener )
531     throw ( uno::RuntimeException )
532 {
533     ::osl::MutexGuard aGuard( m_aMutex );
534     if ( m_bDisposed )
535         throw lang::DisposedException(); // TODO
536 
537     if ( !m_pInterfaceContainer )
538         m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
539 
540     m_pInterfaceContainer->addInterface( ::getCppuType( (const uno::Reference< embed::XStateChangeListener >*)0 ),
541                                                         xListener );
542 }
543 
544 //----------------------------------------------
545 void SAL_CALL OCommonEmbeddedObject::removeStateChangeListener(
546                     const uno::Reference< embed::XStateChangeListener >& xListener )
547     throw (uno::RuntimeException)
548 {
549     ::osl::MutexGuard aGuard( m_aMutex );
550     if ( m_pInterfaceContainer )
551         m_pInterfaceContainer->removeInterface( ::getCppuType( (const uno::Reference< embed::XStateChangeListener >*)0 ),
552                                                 xListener );
553 }
554 
555 //----------------------------------------------
556 void SAL_CALL OCommonEmbeddedObject::close( sal_Bool bDeliverOwnership )
557     throw ( util::CloseVetoException,
558             uno::RuntimeException )
559 {
560     ::osl::MutexGuard aGuard( m_aMutex );
561     if ( m_bClosed )
562         throw lang::DisposedException(); // TODO
563 
564     uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) );
565     lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
566 
567     if ( m_pInterfaceContainer )
568     {
569         ::cppu::OInterfaceContainerHelper* pContainer =
570             m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >*) NULL ) );
571         if ( pContainer != NULL )
572         {
573             ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
574             while (pIterator.hasMoreElements())
575             {
576                 try
577                 {
578                     ((util::XCloseListener*)pIterator.next())->queryClosing( aSource, bDeliverOwnership );
579                 }
580                 catch( uno::RuntimeException& )
581                 {
582                     pIterator.remove();
583                 }
584             }
585         }
586 
587         pContainer = m_pInterfaceContainer->getContainer(
588                                     ::getCppuType( ( const uno::Reference< util::XCloseListener >*) NULL ) );
589         if ( pContainer != NULL )
590         {
591             ::cppu::OInterfaceIteratorHelper pCloseIterator(*pContainer);
592             while (pCloseIterator.hasMoreElements())
593             {
594                 try
595                 {
596                     ((util::XCloseListener*)pCloseIterator.next())->notifyClosing( aSource );
597                 }
598                 catch( uno::RuntimeException& )
599                 {
600                     pCloseIterator.remove();
601                 }
602             }
603         }
604 
605         m_pInterfaceContainer->disposeAndClear( aSource );
606     }
607 
608     m_bDisposed = sal_True; // the object is disposed now for outside
609 
610     // it is possible that the document can not be closed, in this case if the argument is false
611     // the exception will be thrown otherwise in addition to exception the object must register itself
612     // as termination listener and listen for document events
613 
614     if ( m_pDocHolder )
615     {
616         m_pDocHolder->CloseFrame();
617 
618         try {
619             m_pDocHolder->CloseDocument( bDeliverOwnership, bDeliverOwnership );
620         }
621         catch( uno::Exception& )
622         {
623             if ( bDeliverOwnership )
624             {
625                 m_pDocHolder->release();
626                 m_pDocHolder = NULL;
627                 m_bClosed = sal_True;
628             }
629 
630             throw;
631         }
632 
633         m_pDocHolder->FreeOffice();
634 
635         m_pDocHolder->release();
636         m_pDocHolder = NULL;
637     }
638 
639     // TODO: for now the storage will be disposed by the object, but after the document
640     // will use the storage, the storage will be disposed by the document and recreated by the object
641     if ( m_xObjectStorage.is() )
642     {
643         uno::Reference< lang::XComponent > xComp( m_xObjectStorage, uno::UNO_QUERY );
644         OSL_ENSURE( xComp.is(), "Storage does not support XComponent!\n" );
645 
646         if ( xComp.is() )
647         {
648             try {
649                 xComp->dispose();
650             } catch ( uno::Exception& ) {}
651         }
652 
653         m_xObjectStorage.clear();
654         m_xRecoveryStorage.clear();
655     }
656 
657     m_bClosed = sal_True; // the closing succeeded
658 }
659 
660 //----------------------------------------------
661 void SAL_CALL OCommonEmbeddedObject::addCloseListener( const uno::Reference< util::XCloseListener >& xListener )
662     throw ( uno::RuntimeException )
663 {
664     ::osl::MutexGuard aGuard( m_aMutex );
665     if ( m_bDisposed )
666         throw lang::DisposedException(); // TODO
667 
668     if ( !m_pInterfaceContainer )
669         m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
670 
671     m_pInterfaceContainer->addInterface( ::getCppuType( (const uno::Reference< util::XCloseListener >*)0 ), xListener );
672 }
673 
674 //----------------------------------------------
675 void SAL_CALL OCommonEmbeddedObject::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener )
676     throw (uno::RuntimeException)
677 {
678     ::osl::MutexGuard aGuard( m_aMutex );
679     if ( m_pInterfaceContainer )
680         m_pInterfaceContainer->removeInterface( ::getCppuType( (const uno::Reference< util::XCloseListener >*)0 ),
681                                                 xListener );
682 }
683 
684 //------------------------------------------------------
685 void SAL_CALL OCommonEmbeddedObject::addEventListener( const uno::Reference< document::XEventListener >& xListener )
686         throw ( uno::RuntimeException )
687 {
688     ::osl::MutexGuard aGuard( m_aMutex );
689     if ( m_bDisposed )
690         throw lang::DisposedException(); // TODO
691 
692     if ( !m_pInterfaceContainer )
693         m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
694 
695     m_pInterfaceContainer->addInterface( ::getCppuType( (const uno::Reference< document::XEventListener >*)0 ), xListener );
696 }
697 
698 //------------------------------------------------------
699 void SAL_CALL OCommonEmbeddedObject::removeEventListener( const uno::Reference< document::XEventListener >& xListener )
700         throw ( uno::RuntimeException )
701 {
702     ::osl::MutexGuard aGuard( m_aMutex );
703     if ( m_pInterfaceContainer )
704         m_pInterfaceContainer->removeInterface( ::getCppuType( (const uno::Reference< document::XEventListener >*)0 ),
705                                                 xListener );
706 }
707 
708