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