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_unotools.hxx"
30 #include <unotools/sharedunocomponent.hxx>
31 #include <com/sun/star/lang/XComponent.hpp>
32 #include <com/sun/star/util/XCloseable.hpp>
33 #include <cppuhelper/implbase1.hxx>
34 #include <tools/debug.hxx>
35 
36 //............................................................................
37 namespace utl
38 {
39 //............................................................................
40 
41     using ::com::sun::star::uno::XInterface;
42     using ::com::sun::star::uno::Reference;
43     using ::com::sun::star::uno::Exception;
44     using ::com::sun::star::uno::UNO_QUERY;
45     using ::com::sun::star::uno::RuntimeException;
46     using ::com::sun::star::lang::XComponent;
47     using ::com::sun::star::lang::EventObject;
48     using ::com::sun::star::util::XCloseable;
49     using ::com::sun::star::util::XCloseListener;
50     using ::com::sun::star::util::CloseVetoException;
51 
52     //========================================================================
53     //= DisposableComponent
54     //========================================================================
55     //------------------------------------------------------------------------
56     DisposableComponent::DisposableComponent( const Reference< XInterface >& _rxComponent )
57         :m_xComponent( _rxComponent, UNO_QUERY )
58     {
59         DBG_ASSERT( m_xComponent.is() || !_rxComponent.is(), "DisposableComponent::DisposableComponent: should be an XComponent!" );
60     }
61 
62     //------------------------------------------------------------------------
63     DisposableComponent::~DisposableComponent()
64     {
65         if ( m_xComponent.is() )
66         {
67             try
68             {
69                 m_xComponent->dispose();
70             }
71             catch( const Exception& )
72             {
73                 OSL_ENSURE( sal_False, "DisposableComponent::~DisposableComponent: caught an exception!" );
74             }
75             m_xComponent.clear();
76         }
77     }
78 
79     //========================================================================
80     //= CloseableComponentImpl
81     //========================================================================
82     DBG_NAME( CloseableComponentImpl )
83     typedef ::cppu::WeakImplHelper1 <   XCloseListener
84                                     >   CloseableComponentImpl_Base;
85     class CloseableComponentImpl : public CloseableComponentImpl_Base
86     {
87     private:
88         Reference< XCloseable > m_xCloseable;
89 
90     public:
91         CloseableComponentImpl( const Reference< XInterface >& _rxComponent );
92 
93         /** closes the component
94 
95             @nofail
96         */
97         void    nf_closeComponent();
98 
99     protected:
100         virtual ~CloseableComponentImpl();
101 
102         // XCloseListener overridables
103         virtual void SAL_CALL queryClosing( const EventObject& Source, ::sal_Bool GetsOwnership ) throw (CloseVetoException, RuntimeException);
104         virtual void SAL_CALL notifyClosing( const EventObject& Source ) throw (RuntimeException);
105 
106         // XEventListener overridables
107         virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
108 
109     private:
110         /** starts or stops being a CloseListener at the component
111 
112             Only to be called upon construction of the instance, or when the component
113             is to be closed.
114 
115         @nofail
116         */
117         void    impl_nf_switchListening( bool _bListen );
118 
119 
120     private:
121         CloseableComponentImpl();                                           // never implemented
122         CloseableComponentImpl( const CloseableComponentImpl& );            // never implemented
123         CloseableComponentImpl& operator=( const CloseableComponentImpl& ); // never implemented
124     };
125 
126     //------------------------------------------------------------------------
127     CloseableComponentImpl::CloseableComponentImpl( const Reference< XInterface >& _rxComponent )
128         :m_xCloseable( _rxComponent, UNO_QUERY )
129     {
130         DBG_CTOR( CloseableComponentImpl, NULL );
131         DBG_ASSERT( m_xCloseable.is() || !_rxComponent.is(), "CloseableComponentImpl::CloseableComponentImpl: component is not an XCloseable!" );
132         impl_nf_switchListening( true );
133     }
134     //------------------------------------------------------------------------
135     CloseableComponentImpl::~CloseableComponentImpl()
136     {
137         nf_closeComponent();
138         DBG_DTOR( CloseableComponentImpl, NULL );
139     }
140 
141     //------------------------------------------------------------------------
142     void CloseableComponentImpl::nf_closeComponent()
143     {
144         if ( !m_xCloseable.is() )
145             // nothing to do
146             return;
147 
148         // stop listening
149         impl_nf_switchListening( false );
150 
151         // close
152         try
153         {
154             m_xCloseable->close( sal_True );
155         }
156         catch( const CloseVetoException& ) { /* fine */ }
157         catch( const Exception& )
158         {
159         	OSL_ENSURE( sal_False, "CloseableComponentImpl::nf_closeComponent: caught an unexpected exception!" );
160         }
161 
162         // reset
163         m_xCloseable.clear();
164     }
165 
166     //------------------------------------------------------------------------
167     void CloseableComponentImpl::impl_nf_switchListening( bool _bListen )
168     {
169         if ( !m_xCloseable.is() )
170             return;
171 
172         try
173         {
174             if ( _bListen )
175                 m_xCloseable->addCloseListener( this );
176             else
177                 m_xCloseable->removeCloseListener( this );
178         }
179         catch( const Exception& )
180         {
181         	OSL_ENSURE( sal_False, "CloseableComponentImpl::impl_nf_switchListening: caught an exception!" );
182         }
183     }
184 
185     //--------------------------------------------------------------------
186     void SAL_CALL CloseableComponentImpl::queryClosing( const EventObject&
187     #ifdef DBG_UTIL
188     Source
189     #endif
190     , ::sal_Bool /*GetsOwnership*/ ) throw (CloseVetoException, RuntimeException)
191     {
192         // as long as we live, somebody wants to keep the object alive. So, veto the
193         // closing
194         DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::queryClosing: where did this come from?" );
195         throw CloseVetoException();
196     }
197 
198     //--------------------------------------------------------------------
199     void SAL_CALL CloseableComponentImpl::notifyClosing( const EventObject&
200     #ifdef DBG_UTIL
201     Source
202     #endif
203     ) throw (RuntimeException)
204     {
205         DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::notifyClosing: where did this come from?" );
206 
207         // this should be unreachable: As long as we're a CloseListener, we veto the closing. If we're going
208         // to close the component ourself, then we revoke ourself as listener *before* the close call. So,
209         // if this here fires, something went definately wrong.
210         DBG_ERROR( "CloseableComponentImpl::notifyClosing: unreachable!" );
211     }
212 
213     //--------------------------------------------------------------------
214     void SAL_CALL CloseableComponentImpl::disposing( const EventObject&
215     #ifdef DBG_UTIL
216     Source
217     #endif
218     ) throw (RuntimeException)
219     {
220         DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::disposing: where did this come from?" );
221         DBG_ERROR( "CloseableComponentImpl::disposing: unreachable!" );
222             // same reasoning for this assertion as in ->notifyClosing
223     }
224 
225     //========================================================================
226     //= CloseableComponentImpl
227     //========================================================================
228     DBG_NAME( CloseableComponent )
229     //------------------------------------------------------------------------
230     CloseableComponent::CloseableComponent( const Reference< XInterface >& _rxComponent )
231         :m_pImpl( new CloseableComponentImpl( _rxComponent ) )
232     {
233         DBG_CTOR( CloseableComponent, NULL );
234     }
235 
236     //------------------------------------------------------------------------
237     CloseableComponent::~CloseableComponent()
238     {
239         // close the component, deliver ownership to anybody who wants to veto the close
240         m_pImpl->nf_closeComponent();
241         DBG_DTOR( CloseableComponent, NULL );
242     }
243 
244 //............................................................................
245 }   // namespace utl
246 //............................................................................
247