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 ) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException );
73 virtual void _getPropertyValues( const PropertyMapEntry** ppEntries, Any* pValue ) throw( UnknownPropertyException, WrappedTargetException );
74
75 public:
76 GenericPropertySet( PropertySetInfo* pInfo ) throw();
77 virtual ~GenericPropertySet() throw();
78
79 // XInterface
80 virtual Any SAL_CALL queryAggregation( const Type & rType ) throw( RuntimeException);
81 virtual Any SAL_CALL queryInterface( const Type & rType ) throw( RuntimeException);
82 virtual void SAL_CALL acquire() throw();
83 virtual void SAL_CALL release() throw();
84
85 // XTypeProvider
86 virtual Sequence< Type > SAL_CALL getTypes( ) throw( RuntimeException);
87 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw( RuntimeException);
88
89 // XServiceInfo
90 virtual rtl::OUString SAL_CALL getImplementationName() throw( RuntimeException );
91 virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) throw( RuntimeException );
92 virtual Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( RuntimeException );
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 ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
96 virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
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 ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
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 ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
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 throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException )
160 {
161 ResettableMutexGuard aGuard( maMutex );
162
163 while( *ppEntries )
164 {
165 const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US );
166 OInterfaceContainerHelper * pHelper = m_aListener.getContainer(aPropertyName);
167
168 maAnyMap[ aPropertyName ] = *pValues;
169
170 if ( pHelper )
171 {
172 PropertyChangeEvent aEvt;
173 aEvt.PropertyName = aPropertyName;
174 aEvt.NewValue = *pValues;
175 aGuard.clear();
176 pHelper->notifyEach( &XPropertyChangeListener::propertyChange, aEvt );
177 aGuard.reset();
178 }
179
180 ppEntries++;
181 pValues++;
182 }
183 }
184
_getPropertyValues(const comphelper::PropertyMapEntry ** ppEntries,Any * pValue)185 void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, Any* pValue )
186 throw( UnknownPropertyException, WrappedTargetException )
187 {
188 MutexGuard aGuard( maMutex );
189
190 while( *ppEntries )
191 {
192 const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US );
193 *pValue = maAnyMap[ aPropertyName ];
194
195 ppEntries++;
196 pValue++;
197 }
198 }
199
200 // XInterface
201
queryInterface(const Type & rType)202 Any SAL_CALL GenericPropertySet::queryInterface( const Type & rType )
203 throw( RuntimeException )
204 {
205 return OWeakAggObject::queryInterface( rType );
206 }
207
queryAggregation(const Type & rType)208 Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType )
209 throw(RuntimeException)
210 {
211 Any aAny;
212
213 if( rType == ::getCppuType((const Reference< XServiceInfo >*)0) )
214 aAny <<= Reference< XServiceInfo >(this);
215 else if( rType == ::getCppuType((const Reference< XTypeProvider >*)0) )
216 aAny <<= Reference< XTypeProvider >(this);
217 else if( rType == ::getCppuType((const Reference< XPropertySet >*)0) )
218 aAny <<= Reference< XPropertySet >(this);
219 else if( rType == ::getCppuType((const Reference< XMultiPropertySet >*)0) )
220 aAny <<= Reference< XMultiPropertySet >(this);
221 else
222 aAny <<= OWeakAggObject::queryAggregation( rType );
223
224 return aAny;
225 }
226
acquire()227 void SAL_CALL GenericPropertySet::acquire() throw()
228 {
229 OWeakAggObject::acquire();
230 }
231
release()232 void SAL_CALL GenericPropertySet::release() throw()
233 {
234 OWeakAggObject::release();
235 }
236
getTypes()237 uno::Sequence< uno::Type > SAL_CALL GenericPropertySet::getTypes()
238 throw (uno::RuntimeException)
239 {
240 uno::Sequence< uno::Type > aTypes( 5 );
241 uno::Type* pTypes = aTypes.getArray();
242
243 *pTypes++ = ::getCppuType((const uno::Reference< XAggregation>*)0);
244 *pTypes++ = ::getCppuType((const uno::Reference< XServiceInfo>*)0);
245 *pTypes++ = ::getCppuType((const uno::Reference< XTypeProvider>*)0);
246 *pTypes++ = ::getCppuType((const uno::Reference< XPropertySet>*)0);
247 *pTypes++ = ::getCppuType((const uno::Reference< XMultiPropertySet>*)0);
248
249 return aTypes;
250 }
251
getImplementationId()252 uno::Sequence< sal_Int8 > SAL_CALL GenericPropertySet::getImplementationId()
253 throw (uno::RuntimeException)
254 {
255 MutexGuard aGuard( maMutex );
256
257 static uno::Sequence< sal_Int8 > aId;
258 if( aId.getLength() == 0 )
259 {
260 aId.realloc( 16 );
261 rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
262 }
263 return aId;
264 }
265
266 // XServiceInfo
267
supportsService(const OUString & ServiceName)268 sal_Bool SAL_CALL GenericPropertySet::supportsService( const OUString& ServiceName ) throw(RuntimeException)
269 {
270 Sequence< OUString > aSNL( getSupportedServiceNames() );
271 const OUString * pArray = aSNL.getConstArray();
272
273 for( sal_Int32 i = 0; i < aSNL.getLength(); ++i )
274 if( pArray[i] == ServiceName )
275 return sal_True;
276
277 return sal_False;
278 }
279
getImplementationName()280 OUString SAL_CALL GenericPropertySet::getImplementationName() throw( RuntimeException )
281 {
282 return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.comphelper.GenericPropertySet") );
283 }
284
getSupportedServiceNames()285 Sequence< OUString > SAL_CALL GenericPropertySet::getSupportedServiceNames( )
286 throw( RuntimeException )
287 {
288 Sequence< OUString > aSNS( 1 );
289 aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.XPropertySet" ));
290 return aSNS;
291 }
292
GenericPropertySet_CreateInstance(comphelper::PropertySetInfo * pInfo)293 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > comphelper::GenericPropertySet_CreateInstance( comphelper::PropertySetInfo* pInfo )
294 {
295 return (XPropertySet*)new GenericPropertySet( pInfo );
296 }
297
298