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