Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/framework/source/fwi/jobs/configaccess.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 <jobs/configaccess.hxx>
21
#include <services.h>
22
23
#include <com/sun/star/configuration/theDefaultProvider.hpp>
24
#include <com/sun/star/beans/PropertyValue.hpp>
25
#include <com/sun/star/util/XChangesBatch.hpp>
26
#include <utility>
27
28
#include <comphelper/diagnose_ex.hxx>
29
30
namespace framework{
31
32
/**
33
    @short  open the configuration of this job
34
    @descr  We open the configuration of this job only. Not the whole package or the whole
35
            job set. We are interested on our own properties only.
36
            We set the opened configuration access as our member. So any following method,
37
            which needs cfg access, can use it. That prevent us against multiple open/close requests.
38
            But you can use this method to upgrade an already opened configuration too.
39
40
    @param  eMode
41
                force opening of the configuration access in readonly or in read/write mode
42
 */
43
ConfigAccess::ConfigAccess( /*IN*/ css::uno::Reference< css::uno::XComponentContext > xContext,
44
                            /*IN*/ OUString                                     sRoot )
45
3
    : m_xContext    (std::move( xContext))
46
3
    , m_sRoot       (std::move( sRoot    ))
47
3
    , m_eMode       ( E_CLOSED )
48
3
{
49
3
}
50
51
/**
52
    @short  last chance to close an open configuration access point
53
    @descr  In case our user forgot to close this configuration point
54
            in the right way, normally he will run into some trouble -
55
            e.g. losing data.
56
 */
57
ConfigAccess::~ConfigAccess()
58
0
{
59
0
    close();
60
0
}
61
62
/**
63
    @short  return the internal mode of this instance
64
    @descr  May be the outside user need any information about successfully opened
65
            or closed config access point objects. He can control the internal mode to do so.
66
67
    @return The internal open state of this object.
68
 */
69
ConfigAccess::EOpenMode ConfigAccess::getMode() const
70
0
{
71
0
    std::unique_lock g(m_mutex);
72
0
    return m_eMode;
73
0
}
74
75
/**
76
    @short  open the configuration access in the specified mode
77
    @descr  We set the opened configuration access as our member. So any following method,
78
            which needs cfg access, can use it. That prevent us against multiple open/close requests.
79
            But you can use this method to upgrade an already opened configuration too.
80
            It's possible to open a config access in READONLY mode first and "open" it at a second
81
            time within the mode READWRITE. Then we will upgrade it. Downgrade will be possible too.
82
83
            But note: closing will be done explicitly by calling method close() ... not by
84
            downgrading with mode CLOSED!
85
86
    @param  eMode
87
                force (re)opening of the configuration access in readonly or in read/write mode
88
 */
89
void ConfigAccess::open( /*IN*/ EOpenMode eMode )
90
0
{
91
0
    std::unique_lock g(m_mutex);
92
93
    // check if configuration is already open in the right mode.
94
    // By the way: Don't allow closing by using this method!
95
0
    if ( eMode == E_CLOSED || m_eMode == eMode )
96
0
        return;
97
98
    // We have to close the old access point without any question here.
99
    // It will be open again using the new mode.
100
    // can be called without checks! It does the checks by itself ...
101
    // e.g. for already closed or not opened configuration.
102
    // Flushing of all made changes will be done here too.
103
0
    closeImpl();
104
105
    // create the configuration provider, which provides sub access points
106
0
    css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider = css::configuration::theDefaultProvider::get(m_xContext);
107
0
    css::beans::PropertyValue aParam;
108
0
    aParam.Name    = "nodepath";
109
0
    aParam.Value <<= m_sRoot;
110
111
0
    css::uno::Sequence< css::uno::Any > lParams{ css::uno::Any(aParam) };
112
113
    // open it
114
0
    try
115
0
    {
116
0
        if (eMode==E_READONLY)
117
0
            m_xConfig = xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS  , lParams);
118
0
        else
119
0
        if (eMode==E_READWRITE)
120
0
            m_xConfig = xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGUPDATEACCESS, lParams);
121
0
    }
122
0
    catch(const css::uno::Exception&)
123
0
    {
124
0
        TOOLS_INFO_EXCEPTION("fwk", "open config");
125
0
    }
126
127
0
    m_eMode = E_CLOSED;
128
0
    if (m_xConfig.is())
129
0
        m_eMode = eMode;
130
0
}
131
132
/**
133
    @short  close the internal opened configuration access and flush all changes
134
    @descr  It checks, if the given access is valid and react in the right way.
135
            It flushes all changes ... so nobody else must know this state.
136
 */
137
void ConfigAccess::close()
138
0
{
139
0
    std::unique_lock g(m_mutex);
140
0
    closeImpl();
141
0
}
142
143
void ConfigAccess::closeImpl()
144
0
{
145
    // check already closed configuration
146
0
    if (m_xConfig.is())
147
0
    {
148
0
        css::uno::Reference< css::util::XChangesBatch > xFlush(m_xConfig, css::uno::UNO_QUERY);
149
0
        if (xFlush.is())
150
0
            xFlush->commitChanges();
151
0
        m_xConfig.clear();
152
0
        m_eMode   = E_CLOSED;
153
0
    }
154
0
}
155
156
/**
157
    @short  provides an access to the internal wrapped configuration access
158
    @descr  It's not allowed to safe this c++ (!) reference outside. You have
159
            to use it directly. Further you must use our public lock member m_aLock
160
            to synchronize your code with our internal structures and our interface
161
            methods. Acquire it before you call cfg() and release it afterwards immediately.
162
163
            E.g.:   ConfigAccess aAccess(...);
164
                    Guard aReadLock(aAccess.m_aLock);
165
                    Reference< XPropertySet > xSet(aAccess.cfg(), UNO_QUERY);
166
                    Any aProp = xSet->getPropertyValue("...");
167
                    aReadLock.unlock();
168
169
    @attention  During this time it's not allowed to call the methods open() or close()!
170
                Otherwise you will change your own referenced config access. Anything will
171
                be possible then.
172
173
    @return A c++(!) reference to the uno instance of the configuration access point.
174
 */
175
const css::uno::Reference< css::uno::XInterface >& ConfigAccess::cfg()
176
0
{
177
    // must be synchronized from outside!
178
    // => no lock here ...
179
0
    return m_xConfig;
180
0
}
181
182
} // namespace framework
183
184
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */