xref: /trunk/main/framework/source/fwi/classes/propertysethelper.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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