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