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 throw(css::beans::PropertyExistException,
83 css::uno::Exception )
84 {
85 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
86
87 // SAFE ->
88 WriteGuard aWriteLock(m_rLock);
89
90 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(aProperty.Name);
91 if (pIt != m_lProps.end())
92 throw css::beans::PropertyExistException();
93
94 m_lProps[aProperty.Name] = aProperty;
95 // <- SAFE
96 }
97
98 //-----------------------------------------------------------------------------
impl_removePropertyInfo(const::rtl::OUString & sProperty)99 void SAL_CALL PropertySetHelper::impl_removePropertyInfo(const ::rtl::OUString& sProperty)
100 throw(css::beans::UnknownPropertyException,
101 css::uno::Exception )
102 {
103 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
104
105 // SAFE ->
106 WriteGuard aWriteLock(m_rLock);
107
108 PropertySetHelper::TPropInfoHash::iterator pIt = m_lProps.find(sProperty);
109 if (pIt == m_lProps.end())
110 throw css::beans::UnknownPropertyException();
111
112 m_lProps.erase(pIt);
113 // <- SAFE
114 }
115
116 //-----------------------------------------------------------------------------
impl_enablePropertySet()117 void SAL_CALL PropertySetHelper::impl_enablePropertySet()
118 {
119 }
120
121 //-----------------------------------------------------------------------------
impl_disablePropertySet()122 void SAL_CALL PropertySetHelper::impl_disablePropertySet()
123 {
124 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
125
126 // SAFE ->
127 WriteGuard aWriteLock(m_rLock);
128
129 css::uno::Reference< css::uno::XInterface > xThis(static_cast< css::beans::XPropertySet* >(this), css::uno::UNO_QUERY);
130 css::lang::EventObject aEvent(xThis);
131
132 m_lSimpleChangeListener.disposeAndClear(aEvent);
133 m_lVetoChangeListener.disposeAndClear(aEvent);
134 m_lProps.free();
135
136 aWriteLock.unlock();
137 // <- SAFE
138 }
139
140 //-----------------------------------------------------------------------------
impl_existsVeto(const css::beans::PropertyChangeEvent & aEvent)141 sal_Bool PropertySetHelper::impl_existsVeto(const css::beans::PropertyChangeEvent& aEvent)
142 {
143 /* Dont use the lock here!
144 The used helper is threadsafe and it lives for the whole lifetime of
145 our own object.
146 */
147 ::cppu::OInterfaceContainerHelper* pVetoListener = m_lVetoChangeListener.getContainer(aEvent.PropertyName);
148 if (! pVetoListener)
149 return sal_False;
150
151 ::cppu::OInterfaceIteratorHelper pListener(*pVetoListener);
152 while (pListener.hasMoreElements())
153 {
154 try
155 {
156 css::uno::Reference< css::beans::XVetoableChangeListener > xListener(
157 ((css::beans::XVetoableChangeListener*)pListener.next()),
158 css::uno::UNO_QUERY_THROW);
159 xListener->vetoableChange(aEvent);
160 }
161 catch(const css::uno::RuntimeException&)
162 { pListener.remove(); }
163 catch(const css::beans::PropertyVetoException&)
164 { return sal_True; }
165 }
166
167 return sal_False;
168 }
169
170 //-----------------------------------------------------------------------------
impl_notifyChangeListener(const css::beans::PropertyChangeEvent & aEvent)171 void PropertySetHelper::impl_notifyChangeListener(const css::beans::PropertyChangeEvent& aEvent)
172 {
173 /* Dont use the lock here!
174 The used helper is threadsafe and it lives for the whole lifetime of
175 our own object.
176 */
177 ::cppu::OInterfaceContainerHelper* pSimpleListener = m_lSimpleChangeListener.getContainer(aEvent.PropertyName);
178 if (! pSimpleListener)
179 return;
180
181 ::cppu::OInterfaceIteratorHelper pListener(*pSimpleListener);
182 while (pListener.hasMoreElements())
183 {
184 try
185 {
186 css::uno::Reference< css::beans::XPropertyChangeListener > xListener(
187 ((css::beans::XVetoableChangeListener*)pListener.next()),
188 css::uno::UNO_QUERY_THROW);
189 xListener->propertyChange(aEvent);
190 }
191 catch(const css::uno::RuntimeException&)
192 { pListener.remove(); }
193 }
194 }
195
196 //-----------------------------------------------------------------------------
getPropertySetInfo()197 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo()
198 throw(css::uno::RuntimeException)
199 {
200 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
201
202 css::uno::Reference< css::beans::XPropertySetInfo > xInfo(static_cast< css::beans::XPropertySetInfo* >(this), css::uno::UNO_QUERY_THROW);
203 return xInfo;
204 }
205
206 //-----------------------------------------------------------------------------
setPropertyValue(const::rtl::OUString & sProperty,const css::uno::Any & aValue)207 void SAL_CALL PropertySetHelper::setPropertyValue(const ::rtl::OUString& sProperty,
208 const css::uno::Any& aValue )
209 throw(css::beans::UnknownPropertyException,
210 css::beans::PropertyVetoException ,
211 css::lang::IllegalArgumentException ,
212 css::lang::WrappedTargetException ,
213 css::uno::RuntimeException )
214 {
215 // TODO look for e.g. readonly props and reject setProp() call!
216
217 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
218
219 // SAFE ->
220 WriteGuard aWriteLock(m_rLock);
221
222 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
223 if (pIt == m_lProps.end())
224 throw css::beans::UnknownPropertyException();
225
226 css::beans::Property aPropInfo = pIt->second;
227
228 sal_Bool bLocked = sal_True;
229 if (m_bReleaseLockOnCall)
230 {
231 aWriteLock.unlock();
232 bLocked = sal_False;
233 // <- SAFE
234 }
235
236 css::uno::Any aCurrentValue = impl_getPropertyValue(aPropInfo.Name, aPropInfo.Handle);
237
238 if (! bLocked)
239 {
240 // SAFE ->
241 aWriteLock.lock();
242 bLocked = sal_True;
243 }
244
245 sal_Bool bWillBeChanged = (aCurrentValue != aValue);
246 if (! bWillBeChanged)
247 return;
248
249 css::beans::PropertyChangeEvent aEvent;
250 aEvent.PropertyName = aPropInfo.Name;
251 aEvent.Further = sal_False;
252 aEvent.PropertyHandle = aPropInfo.Handle;
253 aEvent.OldValue = aCurrentValue;
254 aEvent.NewValue = aValue;
255 aEvent.Source = css::uno::Reference< css::uno::XInterface >(m_xBroadcaster.get(), css::uno::UNO_QUERY);
256
257 if (m_bReleaseLockOnCall)
258 {
259 aWriteLock.unlock();
260 bLocked = sal_False;
261 // <- SAFE
262 }
263
264 if (impl_existsVeto(aEvent))
265 throw css::beans::PropertyVetoException();
266
267 impl_setPropertyValue(aPropInfo.Name, aPropInfo.Handle, aValue);
268
269 impl_notifyChangeListener(aEvent);
270 }
271
272 //-----------------------------------------------------------------------------
getPropertyValue(const::rtl::OUString & sProperty)273 css::uno::Any SAL_CALL PropertySetHelper::getPropertyValue(const ::rtl::OUString& sProperty)
274 throw(css::beans::UnknownPropertyException,
275 css::lang::WrappedTargetException ,
276 css::uno::RuntimeException )
277 {
278 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
279
280 // SAFE ->
281 ReadGuard aReadLock(m_rLock);
282
283 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
284 if (pIt == m_lProps.end())
285 throw css::beans::UnknownPropertyException();
286
287 css::beans::Property aPropInfo = pIt->second;
288
289 sal_Bool bLocked = sal_True;
290 if (m_bReleaseLockOnCall)
291 {
292 aReadLock.unlock();
293 bLocked = sal_False;
294 // <- SAFE
295 }
296
297 return impl_getPropertyValue(aPropInfo.Name, aPropInfo.Handle);
298 }
299
300 //-----------------------------------------------------------------------------
addPropertyChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XPropertyChangeListener> & xListener)301 void SAL_CALL PropertySetHelper::addPropertyChangeListener(const ::rtl::OUString& sProperty,
302 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
303 throw(css::beans::UnknownPropertyException,
304 css::lang::WrappedTargetException ,
305 css::uno::RuntimeException )
306 {
307 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
308
309 // SAFE ->
310 ReadGuard aReadLock(m_rLock);
311
312 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
313 if (pIt == m_lProps.end())
314 throw css::beans::UnknownPropertyException();
315
316 aReadLock.unlock();
317 // <- SAFE
318
319 m_lSimpleChangeListener.addInterface(sProperty, xListener);
320 }
321
322 //-----------------------------------------------------------------------------
removePropertyChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XPropertyChangeListener> & xListener)323 void SAL_CALL PropertySetHelper::removePropertyChangeListener(const ::rtl::OUString& sProperty,
324 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
325 throw(css::beans::UnknownPropertyException,
326 css::lang::WrappedTargetException ,
327 css::uno::RuntimeException )
328 {
329 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
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_lSimpleChangeListener.removeInterface(sProperty, xListener);
342 }
343
344 //-----------------------------------------------------------------------------
addVetoableChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XVetoableChangeListener> & xListener)345 void SAL_CALL PropertySetHelper::addVetoableChangeListener(const ::rtl::OUString& sProperty,
346 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
347 throw(css::beans::UnknownPropertyException,
348 css::lang::WrappedTargetException ,
349 css::uno::RuntimeException )
350 {
351 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
352
353 // SAFE ->
354 ReadGuard aReadLock(m_rLock);
355
356 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
357 if (pIt == m_lProps.end())
358 throw css::beans::UnknownPropertyException();
359
360 aReadLock.unlock();
361 // <- SAFE
362
363 m_lVetoChangeListener.addInterface(sProperty, xListener);
364 }
365
366 //-----------------------------------------------------------------------------
removeVetoableChangeListener(const::rtl::OUString & sProperty,const css::uno::Reference<css::beans::XVetoableChangeListener> & xListener)367 void SAL_CALL PropertySetHelper::removeVetoableChangeListener(const ::rtl::OUString& sProperty,
368 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
369 throw(css::beans::UnknownPropertyException,
370 css::lang::WrappedTargetException ,
371 css::uno::RuntimeException )
372 {
373 TransactionGuard aTransaction(m_rTransactionManager, E_SOFTEXCEPTIONS);
374
375 // SAFE ->
376 ReadGuard aReadLock(m_rLock);
377
378 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
379 if (pIt == m_lProps.end())
380 throw css::beans::UnknownPropertyException();
381
382 aReadLock.unlock();
383 // <- SAFE
384
385 m_lVetoChangeListener.removeInterface(sProperty, xListener);
386 }
387
388 //-----------------------------------------------------------------------------
getProperties()389 css::uno::Sequence< css::beans::Property > SAL_CALL PropertySetHelper::getProperties()
390 throw(css::uno::RuntimeException)
391 {
392 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
393
394 // SAFE ->
395 ReadGuard aReadLock(m_rLock);
396
397 sal_Int32 c = (sal_Int32)m_lProps.size();
398 css::uno::Sequence< css::beans::Property > lProps(c);
399 PropertySetHelper::TPropInfoHash::const_iterator pIt ;
400
401 for ( pIt = m_lProps.begin();
402 pIt != m_lProps.end() ;
403 ++pIt )
404 {
405 lProps[--c] = pIt->second;
406 }
407
408 return lProps;
409 // <- SAFE
410 }
411
412 //-----------------------------------------------------------------------------
getPropertyByName(const::rtl::OUString & sName)413 css::beans::Property SAL_CALL PropertySetHelper::getPropertyByName(const ::rtl::OUString& sName)
414 throw(css::beans::UnknownPropertyException,
415 css::uno::RuntimeException )
416 {
417 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
418
419 // SAFE ->
420 ReadGuard aReadLock(m_rLock);
421
422 PropertySetHelper::TPropInfoHash::const_iterator pIt = m_lProps.find(sName);
423 if (pIt == m_lProps.end())
424 throw css::beans::UnknownPropertyException();
425
426 return pIt->second;
427 // <- SAFE
428 }
429
430 //-----------------------------------------------------------------------------
hasPropertyByName(const::rtl::OUString & sName)431 sal_Bool SAL_CALL PropertySetHelper::hasPropertyByName(const ::rtl::OUString& sName)
432 throw(css::uno::RuntimeException)
433 {
434 TransactionGuard aTransaction(m_rTransactionManager, E_HARDEXCEPTIONS);
435
436 // SAFE ->
437 ReadGuard aReadLock(m_rLock);
438
439 PropertySetHelper::TPropInfoHash::iterator pIt = m_lProps.find(sName);
440 sal_Bool bExist = (pIt != m_lProps.end());
441
442 return bExist;
443 // <- SAFE
444 }
445
446 } // namespace framework
447