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