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 // MARKER(update_precomp.py): autogen include statement, do not remove
24 #include "precompiled_connectivity.hxx"
25 #include <connectivity/paramwrapper.hxx>
26 
27 /** === begin UNO includes === **/
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <com/sun/star/sdbc/DataType.hpp>
30 #include <com/sun/star/lang/WrappedTargetException.hpp>
31 #include <com/sun/star/sdb/XParametersSupplier.hpp>
32 #include <com/sun/star/lang/DisposedException.hpp>
33 /** === end UNO includes === **/
34 
35 #include <tools/diagnose_ex.h>
36 #include <comphelper/enumhelper.hxx>
37 
38 #define PROPERTY_ID_VALUE   1000
39 
40 //........................................................................
41 namespace dbtools
42 {
43 namespace param
44 {
45 //........................................................................
46 
47     /** === begin UNO using === **/
48     using ::com::sun::star::uno::Reference;
49     using ::com::sun::star::beans::XPropertySet;
50     using ::com::sun::star::sdbc::XParameters;
51     using ::com::sun::star::uno::Sequence;
52     using ::com::sun::star::uno::Type;
53     using ::com::sun::star::uno::RuntimeException;
54     using ::com::sun::star::uno::XWeak;
55     using ::com::sun::star::beans::XPropertySet;
56     using ::com::sun::star::beans::XFastPropertySet;
57     using ::com::sun::star::beans::XMultiPropertySet;
58     using ::com::sun::star::beans::XPropertySetInfo;
59     using ::com::sun::star::beans::Property;
60     using ::com::sun::star::uno::Exception;
61     using ::com::sun::star::uno::UNO_QUERY_THROW;
62     using ::com::sun::star::uno::Any;
63     using ::com::sun::star::lang::IllegalArgumentException;
64     using ::com::sun::star::sdbc::SQLException;
65     using ::com::sun::star::lang::WrappedTargetException;
66     using ::com::sun::star::lang::IndexOutOfBoundsException;
67     using ::com::sun::star::container::XEnumeration;
68     using ::com::sun::star::sdb::XSingleSelectQueryAnalyzer;
69     using ::com::sun::star::sdb::XParametersSupplier;
70     using ::com::sun::star::lang::DisposedException;
71     /** === end UNO using === **/
72     namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
73     namespace DataType = ::com::sun::star::sdbc::DataType;
74 
75     //====================================================================
76     //= ParameterWrapper
77     //====================================================================
78     //--------------------------------------------------------------------
ParameterWrapper(const Reference<XPropertySet> & _rxColumn)79     ParameterWrapper::ParameterWrapper( const Reference< XPropertySet >& _rxColumn )
80         :PropertyBase( m_aBHelper )
81         ,m_xDelegator( _rxColumn )
82     {
83         if ( m_xDelegator.is() )
84             m_xDelegatorPSI = m_xDelegator->getPropertySetInfo();
85         if ( !m_xDelegatorPSI.is() )
86             throw RuntimeException();
87     }
88 
89     //--------------------------------------------------------------------
ParameterWrapper(const Reference<XPropertySet> & _rxColumn,const Reference<XParameters> & _rxAllParameters,const::std::vector<sal_Int32> & _rIndexes)90     ParameterWrapper::ParameterWrapper( const Reference< XPropertySet >& _rxColumn,
91             const Reference< XParameters >& _rxAllParameters, const ::std::vector< sal_Int32 >& _rIndexes )
92         :PropertyBase( m_aBHelper )
93         ,m_aIndexes( _rIndexes )
94         ,m_xDelegator( _rxColumn )
95         ,m_xValueDestination( _rxAllParameters )
96     {
97         if ( m_xDelegator.is() )
98             m_xDelegatorPSI = m_xDelegator->getPropertySetInfo();
99         if ( !m_xDelegatorPSI.is() )
100             throw RuntimeException();
101 
102         OSL_ENSURE( !m_aIndexes.empty(), "ParameterWrapper::ParameterWrapper: sure about the indexes?" );
103     }
104 
105     //--------------------------------------------------------------------
~ParameterWrapper()106     ParameterWrapper::~ParameterWrapper()
107     {
108     }
109 
110     //--------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2(ParameterWrapper,UnoBase,PropertyBase)111     IMPLEMENT_FORWARD_XINTERFACE2( ParameterWrapper, UnoBase, PropertyBase )
112 
113     //--------------------------------------------------------------------
114     Sequence< Type > SAL_CALL ParameterWrapper::getTypes(   ) throw(RuntimeException)
115     {
116         Sequence< Type > aTypes( 4 );
117         aTypes[ 1 ] = ::getCppuType( static_cast< Reference< XWeak >*             >( NULL ) );
118         aTypes[ 1 ] = ::getCppuType( static_cast< Reference< XPropertySet >*      >( NULL ) );
119         aTypes[ 2 ] = ::getCppuType( static_cast< Reference< XFastPropertySet >*  >( NULL ) );
120         aTypes[ 3 ] = ::getCppuType( static_cast< Reference< XMultiPropertySet >* >( NULL ) );
121         return aTypes;
122     }
123 
124     //--------------------------------------------------------------------
IMPLEMENT_GET_IMPLEMENTATION_ID(ParameterWrapper)125     IMPLEMENT_GET_IMPLEMENTATION_ID( ParameterWrapper )
126 
127     //--------------------------------------------------------------------
128     ::rtl::OUString ParameterWrapper::impl_getPseudoAggregatePropertyName( sal_Int32 _nHandle ) const
129     {
130         Reference< XPropertySetInfo >  xInfo = const_cast<ParameterWrapper*>( this )->getPropertySetInfo();
131         Sequence< Property > aProperties = xInfo->getProperties();
132         const Property* pProperties = aProperties.getConstArray();
133         for ( sal_Int32 i = 0; i < aProperties.getLength(); ++i, ++pProperties )
134         {
135             if ( pProperties->Handle == _nHandle )
136                 return pProperties->Name;
137         }
138 
139         OSL_ENSURE( sal_False, "ParameterWrapper::impl_getPseudoAggregatePropertyName: invalid argument!" );
140         return ::rtl::OUString();
141     }
142 
143     //--------------------------------------------------------------------
getPropertySetInfo()144     Reference< XPropertySetInfo > ParameterWrapper::getPropertySetInfo() throw( RuntimeException )
145     {
146         return createPropertySetInfo( getInfoHelper() );
147     }
148 
149     //--------------------------------------------------------------------
getInfoHelper()150     ::cppu::IPropertyArrayHelper& ParameterWrapper::getInfoHelper()
151     {
152         if ( !m_pInfoHelper.get() )
153         {
154             Sequence< Property > aProperties;
155             try
156             {
157                 aProperties = m_xDelegatorPSI->getProperties();
158                 sal_Int32 nProperties( aProperties.getLength() );
159                 aProperties.realloc( nProperties + 1 );
160                 aProperties[ nProperties ] = Property(
161                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value" ) ),
162                     PROPERTY_ID_VALUE,
163                     ::cppu::UnoType< Any >::get(),
164                     PropertyAttribute::TRANSIENT | PropertyAttribute::MAYBEVOID
165                 );
166             }
167             catch( const Exception& )
168             {
169                 DBG_UNHANDLED_EXCEPTION();
170             }
171 
172             m_pInfoHelper.reset( new ::cppu::OPropertyArrayHelper( aProperties, false ) );
173         }
174         return *m_pInfoHelper;
175     }
176 
177     //--------------------------------------------------------------------
convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)178     sal_Bool ParameterWrapper::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) throw( IllegalArgumentException )
179     {
180         OSL_ENSURE( PROPERTY_ID_VALUE == nHandle, "ParameterWrapper::convertFastPropertyValue: the only non-readonly prop should be our PROPERTY_VALUE!" );
181         (void)nHandle;
182 
183         // we're lazy here ...
184         rOldValue = m_aValue.makeAny();
185         rConvertedValue = rValue;
186         return sal_True;    // assume "modified" ...
187     }
188 
189     //--------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)190     void ParameterWrapper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw( Exception )
191     {
192         if ( nHandle == PROPERTY_ID_VALUE )
193         {
194             try
195             {
196                 // TODO : aParamType & nScale can be obtained within the constructor ....
197                 sal_Int32 nParamType = DataType::VARCHAR;
198                 OSL_VERIFY( m_xDelegator->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ) ) >>= nParamType );
199 
200                 sal_Int32 nScale = 0;
201                 if ( m_xDelegatorPSI->hasPropertyByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scale" ) ) ) )
202                     OSL_VERIFY( m_xDelegator->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scale" ) ) ) >>= nScale );
203 
204                 if ( m_xValueDestination.is() )
205                 {
206                     for ( ::std::vector< sal_Int32 >::iterator aIter = m_aIndexes.begin(); aIter != m_aIndexes.end(); ++aIter )
207                     {
208                         m_xValueDestination->setObjectWithInfo( *aIter + 1, rValue, nParamType, nScale );
209                             // (the index of the parameters is one-based)
210                     }
211                 }
212 
213                 m_aValue = rValue;
214             }
215             catch( SQLException& e )
216             {
217                 WrappedTargetException aExceptionWrapper;
218                 aExceptionWrapper.Context = e.Context;
219                 aExceptionWrapper.Message = e.Message;
220                 aExceptionWrapper.TargetException <<= e;
221                 throw WrappedTargetException( aExceptionWrapper );
222             }
223         }
224         else
225         {
226             ::rtl::OUString aName = impl_getPseudoAggregatePropertyName( nHandle );
227             m_xDelegator->setPropertyValue( aName, rValue );
228         }
229     }
230 
231     //--------------------------------------------------------------------
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const232     void ParameterWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
233     {
234         if ( nHandle == PROPERTY_ID_VALUE )
235         {
236             rValue = m_aValue.makeAny();
237         }
238         else
239         {
240             ::rtl::OUString aName = impl_getPseudoAggregatePropertyName( nHandle );
241             rValue = m_xDelegator->getPropertyValue( aName );
242         }
243     }
244 
245     //--------------------------------------------------------------------
dispose()246     void SAL_CALL ParameterWrapper::dispose()
247     {
248         ::osl::MutexGuard aGuard( m_aMutex );
249 
250         m_aValue.setNull();
251         m_aIndexes.resize(0);
252         m_xDelegator.clear();
253         m_xDelegatorPSI.clear();
254         m_xValueDestination.clear();
255 
256         m_aBHelper.bDisposed = sal_True;
257     }
258 
259     //====================================================================
260     //= ParameterWrapperContainer
261     //====================================================================
262     //--------------------------------------------------------------------
ParameterWrapperContainer()263     ParameterWrapperContainer::ParameterWrapperContainer()
264         :ParameterWrapperContainer_Base( m_aMutex )
265     {
266     }
267 
268     //--------------------------------------------------------------------
ParameterWrapperContainer(const Reference<XSingleSelectQueryAnalyzer> & _rxComposer)269     ParameterWrapperContainer::ParameterWrapperContainer( const Reference< XSingleSelectQueryAnalyzer >& _rxComposer )
270         :ParameterWrapperContainer_Base( m_aMutex )
271     {
272         Reference< XParametersSupplier > xSuppParams( _rxComposer, UNO_QUERY_THROW );
273         Reference< XIndexAccess > xParameters( xSuppParams->getParameters(), UNO_QUERY_THROW );
274         sal_Int32 nParamCount( xParameters->getCount() );
275         m_aParameters.reserve( nParamCount );
276         for ( sal_Int32 i=0; i<nParamCount; ++i )
277         {
278             m_aParameters.push_back( new ParameterWrapper( Reference< XPropertySet >( xParameters->getByIndex( i ), UNO_QUERY_THROW ) ) );
279         }
280     }
281 
282     //--------------------------------------------------------------------
~ParameterWrapperContainer()283     ParameterWrapperContainer::~ParameterWrapperContainer()
284     {
285     }
286 
287     //--------------------------------------------------------------------
getElementType()288     Type SAL_CALL ParameterWrapperContainer::getElementType() throw( RuntimeException )
289     {
290         ::osl::MutexGuard aGuard( m_aMutex );
291         impl_checkDisposed_throw();
292         return ::getCppuType( static_cast< Reference< XPropertySet >* >( NULL ) );
293     }
294 
295     //--------------------------------------------------------------------
hasElements()296     sal_Bool SAL_CALL ParameterWrapperContainer::hasElements() throw( RuntimeException )
297     {
298         ::osl::MutexGuard aGuard( m_aMutex );
299         impl_checkDisposed_throw();
300         return !m_aParameters.empty();
301     }
302 
303     //--------------------------------------------------------------------
getCount()304     sal_Int32 SAL_CALL ParameterWrapperContainer::getCount() throw( RuntimeException )
305     {
306         ::osl::MutexGuard aGuard( m_aMutex );
307         impl_checkDisposed_throw();
308         return m_aParameters.size();
309     }
310 
311     //--------------------------------------------------------------------
getByIndex(sal_Int32 _nIndex)312     Any SAL_CALL ParameterWrapperContainer::getByIndex( sal_Int32 _nIndex ) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
313     {
314         ::osl::MutexGuard aGuard( m_aMutex );
315         impl_checkDisposed_throw();
316 
317         if ( ( _nIndex < 0 ) || ( _nIndex >= (sal_Int32)m_aParameters.size() ) )
318             throw IndexOutOfBoundsException();
319 
320         return makeAny( Reference< XPropertySet >( m_aParameters[ _nIndex ].get() ) );
321     }
322 
323     //--------------------------------------------------------------------
createEnumeration()324     Reference< XEnumeration > ParameterWrapperContainer::createEnumeration() throw( RuntimeException )
325     {
326         ::osl::MutexGuard aGuard( m_aMutex );
327         impl_checkDisposed_throw();
328 
329         return new ::comphelper::OEnumerationByIndex( static_cast< XIndexAccess* >( this ) );
330     }
331 
332     //--------------------------------------------------------------------
impl_checkDisposed_throw()333     void ParameterWrapperContainer::impl_checkDisposed_throw()
334     {
335         if ( rBHelper.bDisposed )
336             throw DisposedException( ::rtl::OUString(), *this );
337     }
338 
339     //--------------------------------------------------------------------
disposing()340     void SAL_CALL ParameterWrapperContainer::disposing()
341     {
342         ::osl::MutexGuard aGuard( m_aMutex );
343         impl_checkDisposed_throw();
344 
345         for (   Parameters::const_iterator param = m_aParameters.begin();
346                 param != m_aParameters.end();
347                 ++param
348             )
349         {
350             (*param)->dispose();
351         }
352 
353         Parameters aEmpty;
354         m_aParameters.swap( aEmpty );
355     }
356 
357 //........................................................................
358 } } // namespace dbtools::param
359 //........................................................................
360 
361