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_comphelper.hxx"
26 #include <com/sun/star/lang/XServiceInfo.hpp>
27 #include <com/sun/star/lang/XTypeProvider.hpp>
28 #include <cppuhelper/weakagg.hxx>
29 #include <cppuhelper/interfacecontainer.hxx>
30 #include <comphelper/propertysethelper.hxx>
31 #include <osl/mutex.hxx>
32 #include <comphelper/genericpropertyset.hxx>
33 #include <comphelper/propertysetinfo.hxx>
34 #include <comphelper/stl_types.hxx>
35 #include <vos/mutex.hxx>
36 #include <rtl/uuid.h>
37 #include <boost/mem_fn.hpp>
38 #include <boost/bind.hpp>
39 #include <boost/utility.hpp>
40
41 ///////////////////////////////////////////////////////////////////////
42
43 using namespace ::rtl;
44 using namespace ::osl;
45 using namespace ::cppu;
46 using namespace ::comphelper;
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::beans;
50 using namespace ::com::sun::star::lang;
51
52 DECLARE_STL_USTRINGACCESS_MAP( Any, GenericAnyMapImpl );
53
54 namespace comphelper
55 {
56 struct IMPL_GenericPropertySet_MutexContainer
57 {
58 Mutex maMutex ;
59 } ;
60
61 class GenericPropertySet : public OWeakAggObject,
62 public XServiceInfo,
63 public XTypeProvider,
64 public PropertySetHelper,
65 private IMPL_GenericPropertySet_MutexContainer
66 {
67 private:
68 GenericAnyMapImpl maAnyMap;
69 ::cppu::OMultiTypeInterfaceContainerHelperVar< ::rtl::OUString,UStringHash,UStringEqual> m_aListener;
70
71 protected:
72 virtual void _setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues );
73 virtual void _getPropertyValues( const PropertyMapEntry** ppEntries, Any* pValue );
74
75 public:
76 GenericPropertySet( PropertySetInfo* pInfo ) throw();
77 virtual ~GenericPropertySet() throw();
78
79 // XInterface
80 virtual Any SAL_CALL queryAggregation( const Type & rType );
81 virtual Any SAL_CALL queryInterface( const Type & rType );
82 virtual void SAL_CALL acquire() throw();
83 virtual void SAL_CALL release() throw();
84
85 // XTypeProvider
86 virtual Sequence< Type > SAL_CALL getTypes( );
87 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( );
88
89 // XServiceInfo
90 virtual rtl::OUString SAL_CALL getImplementationName();
91 virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName );
92 virtual Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames();
93
94 // XPropertySet
95 virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener );
96 virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener );
97 };
98
99 }
100
101 ///////////////////////////////////////////////////////////////////////
102
GenericPropertySet(PropertySetInfo * pInfo)103 GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) throw()
104 : PropertySetHelper( pInfo )
105 ,m_aListener(maMutex)
106 {
107 }
108
~GenericPropertySet()109 GenericPropertySet::~GenericPropertySet() throw()
110 {
111 }
addPropertyChangeListener(const::rtl::OUString & aPropertyName,const Reference<XPropertyChangeListener> & xListener)112 void SAL_CALL GenericPropertySet::addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener )
113 {
114 Reference < XPropertySetInfo > xInfo = getPropertySetInfo( );
115 if ( xInfo.is() )
116 {
117 if ( aPropertyName.isEmpty() )
118 {
119 Sequence< Property> aSeq = xInfo->getProperties();
120 const Property* pIter = aSeq.getConstArray();
121 const Property* pEnd = pIter + aSeq.getLength();
122 for( ; pIter != pEnd ; ++pIter)
123 {
124 m_aListener.addInterface(pIter->Name,xListener);
125 }
126 }
127 else if ( xInfo->hasPropertyByName(aPropertyName) )
128 m_aListener.addInterface(aPropertyName,xListener);
129 else
130 throw UnknownPropertyException( aPropertyName, *this );
131 }
132 }
133
removePropertyChangeListener(const::rtl::OUString & aPropertyName,const Reference<XPropertyChangeListener> & xListener)134 void SAL_CALL GenericPropertySet::removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener )
135 {
136 ResettableMutexGuard aGuard( maMutex );
137 Reference < XPropertySetInfo > xInfo = getPropertySetInfo( );
138 aGuard.clear();
139 if ( xInfo.is() )
140 {
141 if ( aPropertyName.isEmpty() )
142 {
143 Sequence< Property> aSeq = xInfo->getProperties();
144 const Property* pIter = aSeq.getConstArray();
145 const Property* pEnd = pIter + aSeq.getLength();
146 for( ; pIter != pEnd ; ++pIter)
147 {
148 m_aListener.removeInterface(pIter->Name,xListener);
149 }
150 }
151 else if ( xInfo->hasPropertyByName(aPropertyName) )
152 m_aListener.removeInterface(aPropertyName,xListener);
153 else
154 throw UnknownPropertyException( aPropertyName, *this );
155 }
156 }
157
_setPropertyValues(const PropertyMapEntry ** ppEntries,const Any * pValues)158 void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues )
159 {
160 ResettableMutexGuard aGuard( maMutex );
161
162 while( *ppEntries )
163 {
164 const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US );
165 OInterfaceContainerHelper * pHelper = m_aListener.getContainer(aPropertyName);
166
167 maAnyMap[ aPropertyName ] = *pValues;
168
169 if ( pHelper )
170 {
171 PropertyChangeEvent aEvt;
172 aEvt.PropertyName = aPropertyName;
173 aEvt.NewValue = *pValues;
174 aGuard.clear();
175 pHelper->notifyEach( &XPropertyChangeListener::propertyChange, aEvt );
176 aGuard.reset();
177 }
178
179 ppEntries++;
180 pValues++;
181 }
182 }
183
_getPropertyValues(const comphelper::PropertyMapEntry ** ppEntries,Any * pValue)184 void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, Any* pValue )
185 {
186 MutexGuard aGuard( maMutex );
187
188 while( *ppEntries )
189 {
190 const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US );
191 *pValue = maAnyMap[ aPropertyName ];
192
193 ppEntries++;
194 pValue++;
195 }
196 }
197
198 // XInterface
199
queryInterface(const Type & rType)200 Any SAL_CALL GenericPropertySet::queryInterface( const Type & rType )
201 {
202 return OWeakAggObject::queryInterface( rType );
203 }
204
queryAggregation(const Type & rType)205 Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType )
206 {
207 Any aAny;
208
209 if( rType == ::getCppuType((const Reference< XServiceInfo >*)0) )
210 aAny <<= Reference< XServiceInfo >(this);
211 else if( rType == ::getCppuType((const Reference< XTypeProvider >*)0) )
212 aAny <<= Reference< XTypeProvider >(this);
213 else if( rType == ::getCppuType((const Reference< XPropertySet >*)0) )
214 aAny <<= Reference< XPropertySet >(this);
215 else if( rType == ::getCppuType((const Reference< XMultiPropertySet >*)0) )
216 aAny <<= Reference< XMultiPropertySet >(this);
217 else
218 aAny <<= OWeakAggObject::queryAggregation( rType );
219
220 return aAny;
221 }
222
acquire()223 void SAL_CALL GenericPropertySet::acquire() throw()
224 {
225 OWeakAggObject::acquire();
226 }
227
release()228 void SAL_CALL GenericPropertySet::release() throw()
229 {
230 OWeakAggObject::release();
231 }
232
getTypes()233 uno::Sequence< uno::Type > SAL_CALL GenericPropertySet::getTypes()
234 {
235 uno::Sequence< uno::Type > aTypes( 5 );
236 uno::Type* pTypes = aTypes.getArray();
237
238 *pTypes++ = ::getCppuType((const uno::Reference< XAggregation>*)0);
239 *pTypes++ = ::getCppuType((const uno::Reference< XServiceInfo>*)0);
240 *pTypes++ = ::getCppuType((const uno::Reference< XTypeProvider>*)0);
241 *pTypes++ = ::getCppuType((const uno::Reference< XPropertySet>*)0);
242 *pTypes++ = ::getCppuType((const uno::Reference< XMultiPropertySet>*)0);
243
244 return aTypes;
245 }
246
getImplementationId()247 uno::Sequence< sal_Int8 > SAL_CALL GenericPropertySet::getImplementationId()
248 {
249 MutexGuard aGuard( maMutex );
250
251 static uno::Sequence< sal_Int8 > aId;
252 if( aId.getLength() == 0 )
253 {
254 aId.realloc( 16 );
255 rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
256 }
257 return aId;
258 }
259
260 // XServiceInfo
261
supportsService(const OUString & ServiceName)262 sal_Bool SAL_CALL GenericPropertySet::supportsService( const OUString& ServiceName )
263 {
264 Sequence< OUString > aSNL( getSupportedServiceNames() );
265 const OUString * pArray = aSNL.getConstArray();
266
267 for( sal_Int32 i = 0; i < aSNL.getLength(); ++i )
268 if( pArray[i] == ServiceName )
269 return sal_True;
270
271 return sal_False;
272 }
273
getImplementationName()274 OUString SAL_CALL GenericPropertySet::getImplementationName()
275 {
276 return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.comphelper.GenericPropertySet") );
277 }
278
getSupportedServiceNames()279 Sequence< OUString > SAL_CALL GenericPropertySet::getSupportedServiceNames( )
280 {
281 Sequence< OUString > aSNS( 1 );
282 aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.XPropertySet" ));
283 return aSNS;
284 }
285
GenericPropertySet_CreateInstance(comphelper::PropertySetInfo * pInfo)286 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > comphelper::GenericPropertySet_CreateInstance( comphelper::PropertySetInfo* pInfo )
287 {
288 return (XPropertySet*)new GenericPropertySet( pInfo );
289 }
290