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 
103 GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) throw()
104 : PropertySetHelper( pInfo )
105 ,m_aListener(maMutex)
106 {
107 }
108 
109 GenericPropertySet::~GenericPropertySet() throw()
110 {
111 }
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.getLength() )
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 
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.getLength() )
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 
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 
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 
202 Any SAL_CALL GenericPropertySet::queryInterface( const Type & rType )
203 	throw( RuntimeException )
204 {
205 	return OWeakAggObject::queryInterface( rType );
206 }
207 
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 
227 void SAL_CALL GenericPropertySet::acquire() throw()
228 {
229 	OWeakAggObject::acquire();
230 }
231 
232 void SAL_CALL GenericPropertySet::release() throw()
233 {
234 	OWeakAggObject::release();
235 }
236 
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 
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 
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 
280 OUString SAL_CALL GenericPropertySet::getImplementationName() throw( RuntimeException )
281 {
282 	return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.comphelper.GenericPropertySet") );
283 }
284 
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 
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