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_framework.hxx"
26
27 //_________________________________________________________________________________________________________________
28 // my own includes
29
30 #include <classes/propertysethelper.hxx>
31 #include <threadhelp/transactionguard.hxx>
32 #include <threadhelp/readguard.hxx>
33 #include <threadhelp/writeguard.hxx>
34
35 //_________________________________________________________________________________________________________________
36 // interface includes
37
38 //_________________________________________________________________________________________________________________
39 // other includes
40
41 //_________________________________________________________________________________________________________________
42 // namespace
43
44 namespace framework{
45
46 //_________________________________________________________________________________________________________________
47 // non exported definitions
48
49 //-----------------------------------------------------------------------------
PropertySetHelper(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR,LockHelper * pExternalLock,TransactionManager * pExternalTransactionManager,sal_Bool bReleaseLockOnCall)50 PropertySetHelper::PropertySetHelper(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
51 LockHelper* pExternalLock ,
52 TransactionManager* pExternalTransactionManager ,
53 sal_Bool bReleaseLockOnCall )
54 : m_xSMGR (xSMGR )
55 , m_lSimpleChangeListener(pExternalLock->getShareableOslMutex())
56 , m_lVetoChangeListener (pExternalLock->getShareableOslMutex())
57 , m_bReleaseLockOnCall (bReleaseLockOnCall )
58 , m_rLock (*pExternalLock )
59 , m_rTransactionManager (*pExternalTransactionManager )
60 {
61 }
62
63 //-----------------------------------------------------------------------------
~PropertySetHelper()64 PropertySetHelper::~PropertySetHelper()
65 {
66 }
67
68 //-----------------------------------------------------------------------------
impl_setPropertyChangeBroadcaster(const css::uno::Reference<css::uno::XInterface> & xBroadcaster)69 void PropertySetHelper::impl_setPropertyChangeBroadcaster(const css::uno::Reference< css::uno::XInterface >& xBroadcaster)
70 {
71 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
72
73 // SAFE ->
74 WriteGuard aWriteLock(m_rLock);
75 m_xBroadcaster = xBroadcaster;
76 aWriteLock.unlock();
77 // <- SAFE
78 }
79
80 //-----------------------------------------------------------------------------
impl_addPropertyInfo(const css::beans::Property & aProperty)81 void SAL_CALL PropertySetHelper::impl_addPropertyInfo(const css::beans::Property& aProperty)
82 {
83 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
84
85 // SAFE ->
86 WriteGuard aWriteLock(m_rLock);
87
88 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(aProperty.Name);
89 if (pIt != m_lProps.end())
90 throw css::beans::PropertyExistException();
91
92 m_lProps[aProperty.Name] = aProperty;
93 // <- SAFE
94 }
95
96 //-----------------------------------------------------------------------------
impl_removePropertyInfo(const::rtl::OUString & sProperty)97 void SAL_CALL PropertySetHelper::impl_removePropertyInfo(const ::rtl::OUString& sProperty)
98 {
99 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
100
101 // SAFE ->
102 WriteGuard aWriteLock(m_rLock);
103
104 PropertySetHelper::TPropInfoHash::iterator pIt = m_lProps.find(sProperty);
105 if (pIt == m_lProps.end())
106 throw css::beans::UnknownPropertyException();
107
108 m_lProps.erase(pIt);
109 // <- SAFE
110 }
111
112 //-----------------------------------------------------------------------------
impl_enablePropertySet()113 void SAL_CALL PropertySetHelper::impl_enablePropertySet()
114 {
115 }
116
117 //-----------------------------------------------------------------------------
impl_disablePropertySet()118 void SAL_CALL PropertySetHelper::impl_disablePropertySet()
119 {
120 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
121
122 // SAFE ->
123 WriteGuard aWriteLock(m_rLock);
124
125 css::uno::Reference< css::uno::XInterface > xThis(static_cast< css::beans::XPropertySet* >(this), css::uno::UNO_QUERY);
126 css::lang::EventObject aEvent(xThis);
127
128 m_lSimpleChangeListener.disposeAndClear(aEvent);
129 m_lVetoChangeListener.disposeAndClear(aEvent);
130 m_lProps.free();
131
132 aWriteLock.unlock();
133 // <- SAFE
134 }
135
136 //-----------------------------------------------------------------------------
impl_existsVeto(const css::beans::PropertyChangeEvent & aEvent)137 sal_Bool PropertySetHelper::impl_existsVeto(const css::beans::PropertyChangeEvent& aEvent)
138 {
139 /* Dont use the lock here!
140 The used helper is threadsafe and it lives for the whole lifetime of
141 our own object.
142 */
143 ::cppu::OInterfaceContainerHelper* pVetoListener = m_lVetoChangeListener.getContainer(aEvent.PropertyName);
144 if (! pVetoListener)
145 return sal_False;
146
147 ::cppu::OInterfaceIteratorHelper pListener(*pVetoListener);
148 while (pListener.hasMoreElements())
149 {
150 try
151 {
152 css::uno::Reference< css::beans::XVetoableChangeListener > xListener(
153 ((css::beans::XVetoableChangeListener*)pListener.next()),
154 css::uno::UNO_QUERY_THROW);
155 xListener->vetoableChange(aEvent);
156 }
157 catch(const css::uno::RuntimeException&)
158 { pListener.remove(); }
159 catch(const css::beans::PropertyVetoException&)
160 { return sal_True; }
161 }
162
163 return sal_False;
164 }
165
166 //-----------------------------------------------------------------------------
impl_notifyChangeListener(const css::beans::PropertyChangeEvent & aEvent)167 void PropertySetHelper::impl_notifyChangeListener(const css::beans::PropertyChangeEvent& aEvent)
168 {
169 /* Dont use the lock here!
170 The used helper is threadsafe and it lives for the whole lifetime of
171 our own object.
172 */
173 ::cppu::OInterfaceContainerHelper* pSimpleListener = m_lSimpleChangeListener.getContainer(aEvent.PropertyName);
174 if (! pSimpleListener)
175 return;
176
177 ::cppu::OInterfaceIteratorHelper pListener(*pSimpleListener);
178 while (pListener.hasMoreElements())
179 {
180 try
181 {
182 css::uno::Reference< css::beans::XPropertyChangeListener > xListener(
183 ((css::beans::XVetoableChangeListener*)pListener.next()),
184 css::uno::UNO_QUERY_THROW);
185 xListener->propertyChange(aEvent);
186 }
187 catch(const css::uno::RuntimeException&)
188 { pListener.remove(); }
189 }
190 }
191
192 //-----------------------------------------------------------------------------
getPropertySetInfo()193 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo()
194 {
195 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
196
197 css::uno::Reference< css::beans::XPropertySetInfo > xInfo(static_cast< css::beans::XPropertySetInfo* >(this), css::uno::UNO_QUERY_THROW);
198 return xInfo;
199 }
200
201 //-----------------------------------------------------------------------------
setPropertyValue(const::rtl::OUString & sProperty,const css::uno::Any & aValue)202 void SAL_CALL PropertySetHelper::setPropertyValue(const ::rtl::OUString& sProperty,
203 const css::uno::Any& aValue )
204 {
205 // TODO look for e.g. readonly props and reject setProp() call!
206
207 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
208
209 // SAFE ->
210 WriteGuard aWriteLock(m_rLock);
211
212 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
213 if (pIt == m_lProps.end())
214 throw css::beans::UnknownPropertyException();
215
216 css::beans::Property aPropInfo = pIt->second;
217
218 sal_Bool bLocked = sal_True;
219 if (m_bReleaseLockOnCall)
220 {
221 aWriteLock.unlock();
222 bLocked = sal_False;
223 // <- SAFE
224 }
225
226 css::uno::Any aCurrentValue = impl_getPropertyValue(aPropInfo.Name, aPropInfo.Handle);
227
228 if (! bLocked)
229 {
230 // SAFE ->
231 aWriteLock.lock();
232 bLocked = sal_True;
233 }
234
235 sal_Bool bWillBeChanged = (aCurrentValue != aValue);
236 if (! bWillBeChanged)
237 return;
238
239 css::beans::PropertyChangeEvent aEvent;
240 aEvent.PropertyName = aPropInfo.Name;
241 aEvent.Further = sal_False;
242 aEvent.PropertyHandle = aPropInfo.Handle;
243 aEvent.OldValue = aCurrentValue;
244 aEvent.NewValue = aValue;
245 aEvent.Source = css::uno::Reference< css::uno::XInterface >(m_xBroadcaster.get(), css::uno::UNO_QUERY);
246
247 if (m_bReleaseLockOnCall)
248 {
249 aWriteLock.unlock();
250 bLocked = sal_False;
251 // <- SAFE
252 }
253
254 if (impl_existsVeto(aEvent))
255 throw css::beans::PropertyVetoException();
256
257 impl_setPropertyValue(aPropInfo.Name, aPropInfo.Handle, aValue);
258
259 impl_notifyChangeListener(aEvent);
260 }
261
262 //-----------------------------------------------------------------------------
getPropertyValue(const::rtl::OUString & sProperty)263 css::uno::Any SAL_CALL PropertySetHelper::getPropertyValue(const ::rtl::OUString& sProperty)
264 {
265 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
266
267 // SAFE ->
268 ReadGuard aReadLock(m_rLock);
269
270 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
271 if (pIt == m_lProps.end())
272 throw css::beans::UnknownPropertyException();
273
274 css::beans::Property aPropInfo = pIt->second;
275
276 sal_Bool bLocked = sal_True;
277 if (m_bReleaseLockOnCall)
278 {
279 aReadLock.unlock();
280 bLocked = sal_False;
281 // <- SAFE
282 }
283
284 return impl_getPropertyValue(aPropInfo.Name, aPropInfo.Handle);
285 }
286
287 //-----------------------------------------------------------------------------
addPropertyChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XPropertyChangeListener> & xListener)288 void SAL_CALL PropertySetHelper::addPropertyChangeListener(const ::rtl::OUString& sProperty,
289 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
290 {
291 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
292
293 // SAFE ->
294 ReadGuard aReadLock(m_rLock);
295
296 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
297 if (pIt == m_lProps.end())
298 throw css::beans::UnknownPropertyException();
299
300 aReadLock.unlock();
301 // <- SAFE
302
303 m_lSimpleChangeListener.addInterface(sProperty, xListener);
304 }
305
306 //-----------------------------------------------------------------------------
removePropertyChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XPropertyChangeListener> & xListener)307 void SAL_CALL PropertySetHelper::removePropertyChangeListener(const ::rtl::OUString& sProperty,
308 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
309 {
310 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
311
312 // SAFE ->
313 ReadGuard aReadLock(m_rLock);
314
315 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
316 if (pIt == m_lProps.end())
317 throw css::beans::UnknownPropertyException();
318
319 aReadLock.unlock();
320 // <- SAFE
321
322 m_lSimpleChangeListener.removeInterface(sProperty, xListener);
323 }
324
325 //-----------------------------------------------------------------------------
addVetoableChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XVetoableChangeListener> & xListener)326 void SAL_CALL PropertySetHelper::addVetoableChangeListener(const ::rtl::OUString& sProperty,
327 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
328 {
329 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
330
331 // SAFE ->
332 ReadGuard aReadLock(m_rLock);
333
334 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
335 if (pIt == m_lProps.end())
336 throw css::beans::UnknownPropertyException();
337
338 aReadLock.unlock();
339 // <- SAFE
340
341 m_lVetoChangeListener.addInterface(sProperty, xListener);
342 }
343
344 //-----------------------------------------------------------------------------
removeVetoableChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XVetoableChangeListener> & xListener)345 void SAL_CALL PropertySetHelper::removeVetoableChangeListener(const ::rtl::OUString& sProperty,
346 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
347 {
348 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
349
350 // SAFE ->
351 ReadGuard aReadLock(m_rLock);
352
353 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
354 if (pIt == m_lProps.end())
355 throw css::beans::UnknownPropertyException();
356
357 aReadLock.unlock();
358 // <- SAFE
359
360 m_lVetoChangeListener.removeInterface(sProperty, xListener);
361 }
362
363 //-----------------------------------------------------------------------------
getProperties()364 css::uno::Sequence< css::beans::Property > SAL_CALL PropertySetHelper::getProperties()
365 {
366 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
367
368 // SAFE ->
369 ReadGuard aReadLock(m_rLock);
370
371 sal_Int32 c = (sal_Int32)m_lProps.size();
372 css::uno::Sequence< css::beans::Property > lProps(c);
373 PropertySetHelper::TPropInfoHash::const_iterator pIt ;
374
375 for ( pIt = m_lProps.begin();
376 pIt != m_lProps.end() ;
377 ++pIt )
378 {
379 lProps[--c] = pIt->second;
380 }
381
382 return lProps;
383 // <- SAFE
384 }
385
386 //-----------------------------------------------------------------------------
getPropertyByName(const::rtl::OUString & sName)387 css::beans::Property SAL_CALL PropertySetHelper::getPropertyByName(const ::rtl::OUString& sName)
388 {
389 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
390
391 // SAFE ->
392 ReadGuard aReadLock(m_rLock);
393
394 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sName);
395 if (pIt == m_lProps.end())
396 throw css::beans::UnknownPropertyException();
397
398 return pIt->second;
399 // <- SAFE
400 }
401
402 //-----------------------------------------------------------------------------
hasPropertyByName(const::rtl::OUString & sName)403 sal_Bool SAL_CALL PropertySetHelper::hasPropertyByName(const ::rtl::OUString& sName)
404 {
405 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
406
407 // SAFE ->
408 ReadGuard aReadLock(m_rLock);
409
410 PropertySetHelper::TPropInfoHash::iterator pIt = m_lProps.find(sName);
411 sal_Bool bExist = (pIt != m_lProps.end());
412
413 return bExist;
414 // <- SAFE
415 }
416
417 } // namespace framework
418