Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/unotools/source/misc/sharedunocomponent.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sal/config.h>
21
#include <osl/diagnose.h>
22
23
#include <unotools/sharedunocomponent.hxx>
24
#include <com/sun/star/lang/XComponent.hpp>
25
#include <com/sun/star/util/CloseVetoException.hpp>
26
#include <com/sun/star/util/XCloseable.hpp>
27
#include <cppuhelper/implbase.hxx>
28
#include <tools/debug.hxx>
29
#include <comphelper/diagnose_ex.hxx>
30
31
namespace utl
32
{
33
34
    using ::com::sun::star::uno::XInterface;
35
    using ::com::sun::star::uno::Reference;
36
    using ::com::sun::star::uno::Exception;
37
    using ::com::sun::star::uno::UNO_QUERY;
38
    using ::com::sun::star::lang::EventObject;
39
    using ::com::sun::star::util::XCloseable;
40
    using ::com::sun::star::util::XCloseListener;
41
    using ::com::sun::star::util::CloseVetoException;
42
43
    //= DisposableComponent
44
45
    DisposableComponent::DisposableComponent( const Reference< XInterface >& _rxComponent )
46
58.1k
        :m_xComponent( _rxComponent, UNO_QUERY )
47
58.1k
    {
48
58.1k
        DBG_ASSERT( m_xComponent.is() || !_rxComponent.is(), "DisposableComponent::DisposableComponent: should be an XComponent!" );
49
58.1k
    }
50
51
    DisposableComponent::~DisposableComponent()
52
58.1k
    {
53
58.1k
        if ( m_xComponent.is() )
54
58.1k
        {
55
58.1k
            try
56
58.1k
            {
57
58.1k
                m_xComponent->dispose();
58
58.1k
            }
59
58.1k
            catch( const Exception& )
60
58.1k
            {
61
0
                TOOLS_WARN_EXCEPTION( "unotools", "DisposableComponent::~DisposableComponent" );
62
0
            }
63
58.1k
            m_xComponent.clear();
64
58.1k
        }
65
58.1k
    }
66
67
    typedef ::cppu::WeakImplHelper <   XCloseListener
68
                                    >   CloseableComponentImpl_Base;
69
    class CloseableComponentImpl : public CloseableComponentImpl_Base
70
    {
71
    private:
72
        Reference< XCloseable > m_xCloseable;
73
74
        CloseableComponentImpl(const CloseableComponentImpl&) = delete;
75
        CloseableComponentImpl& operator=(const CloseableComponentImpl&) = delete;
76
77
    public:
78
        explicit CloseableComponentImpl( const Reference< XInterface >& _rxComponent );
79
80
        /** closes the component
81
82
            @nofail
83
        */
84
        void    nf_closeComponent();
85
86
    protected:
87
        virtual ~CloseableComponentImpl() override;
88
89
        // XCloseListener overridables
90
        virtual void SAL_CALL queryClosing( const EventObject& Source, sal_Bool GetsOwnership ) override;
91
        virtual void SAL_CALL notifyClosing( const EventObject& Source ) override;
92
93
        // XEventListener overridables
94
        virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
95
96
    private:
97
        /** starts or stops being a CloseListener at the component
98
99
            Only to be called upon construction of the instance, or when the component
100
            is to be closed.
101
102
        @nofail
103
        */
104
        void    impl_nf_switchListening( bool _bListen );
105
    };
106
107
    CloseableComponentImpl::CloseableComponentImpl( const Reference< XInterface >& _rxComponent )
108
0
        :m_xCloseable( _rxComponent, UNO_QUERY )
109
0
    {
110
0
        DBG_ASSERT( m_xCloseable.is() || !_rxComponent.is(), "CloseableComponentImpl::CloseableComponentImpl: component is not an XCloseable!" );
111
0
        impl_nf_switchListening( true );
112
0
    }
113
114
    CloseableComponentImpl::~CloseableComponentImpl()
115
0
    {
116
0
        nf_closeComponent();
117
0
    }
118
119
    void CloseableComponentImpl::nf_closeComponent()
120
0
    {
121
0
        if ( !m_xCloseable.is() )
122
            // nothing to do
123
0
            return;
124
125
        // stop listening
126
0
        impl_nf_switchListening( false );
127
128
        // close
129
0
        try
130
0
        {
131
0
            m_xCloseable->close( true );
132
0
        }
133
0
        catch( const CloseVetoException& ) { /* fine */ }
134
0
        catch( const Exception& )
135
0
        {
136
0
            TOOLS_WARN_EXCEPTION( "unotools", "CloseableComponentImpl::nf_closeComponent: caught an unexpected exception!" );
137
0
        }
138
139
        // reset
140
0
        m_xCloseable.clear();
141
0
    }
142
143
    void CloseableComponentImpl::impl_nf_switchListening( bool _bListen )
144
0
    {
145
0
        if ( !m_xCloseable.is() )
146
0
            return;
147
148
0
        try
149
0
        {
150
0
            if ( _bListen )
151
0
                m_xCloseable->addCloseListener( this );
152
0
            else
153
0
                m_xCloseable->removeCloseListener( this );
154
0
        }
155
0
        catch( const Exception& )
156
0
        {
157
0
            TOOLS_WARN_EXCEPTION( "unotools", "CloseableComponentImpl::impl_nf_switchListening" );
158
0
        }
159
0
    }
160
161
    void SAL_CALL CloseableComponentImpl::queryClosing( const EventObject& Source, sal_Bool /*GetsOwnership*/ )
162
0
    {
163
        // as long as we live, somebody wants to keep the object alive. So, veto the
164
        // closing
165
0
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::queryClosing: where did this come from?" );
166
0
        throw CloseVetoException();
167
0
    }
168
169
    void SAL_CALL CloseableComponentImpl::notifyClosing( const EventObject& Source )
170
0
    {
171
0
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::notifyClosing: where did this come from?" );
172
173
        // this should be unreachable: As long as we're a CloseListener, we veto the closing. If we're going
174
        // to close the component ourself, then we revoke ourself as listener *before* the close call. So,
175
        // if this here fires, something went definitely wrong.
176
0
        OSL_FAIL( "CloseableComponentImpl::notifyClosing: unreachable!" );
177
0
    }
178
179
    void SAL_CALL CloseableComponentImpl::disposing( const EventObject& Source )
180
0
    {
181
0
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::disposing: where did this come from?" );
182
0
        OSL_FAIL( "CloseableComponentImpl::disposing: unreachable!" );
183
            // same reasoning for this assertion as in ->notifyClosing
184
0
    }
185
186
    CloseableComponent::CloseableComponent( const Reference< XInterface >& _rxComponent )
187
0
        :m_pImpl( new CloseableComponentImpl( _rxComponent ) )
188
0
    {
189
0
    }
190
191
    CloseableComponent::~CloseableComponent()
192
0
    {
193
        // close the component, deliver ownership to anybody who wants to veto the close
194
0
        m_pImpl->nf_closeComponent();
195
0
    }
196
197
}   // namespace utl
198
199
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */