update dev300-m57
[ooovba.git] / cppuhelper / source / implbase_ex.cxx
blobaaf049e8e5fe0ff14015574ee8e29fc0825a2e75
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: implbase_ex.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppuhelper.hxx"
33 #include <sal/alloca.h>
35 #include <string.h>
36 #include <osl/diagnose.h>
37 #include <rtl/byteseq.hxx>
38 #include <rtl/ustrbuf.hxx>
39 #include <rtl/uuid.h>
40 #include <cppuhelper/compbase_ex.hxx>
42 #include "com/sun/star/uno/RuntimeException.hpp"
44 using namespace ::cppu;
45 using namespace ::osl;
46 using namespace ::rtl;
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::uno;
50 namespace cppu
53 /** Shared mutex for implementation helper initialization.
54 Not for public use.
56 ::osl::Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW( () );
58 //--------------------------------------------------------------------------------------------------
59 static inline void checkInterface( Type const & rType )
60 SAL_THROW( (RuntimeException) )
62 if (TypeClass_INTERFACE != rType.getTypeClass())
64 OUStringBuffer buf( 64 );
65 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("querying for interface \"") );
66 buf.append( rType.getTypeName() );
67 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": no interface type!") );
68 OUString msg( buf.makeStringAndClear() );
69 #if OSL_DEBUG_LEVEL > 0
70 OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
71 OSL_ENSURE( 0, str.getStr() );
72 #endif
73 throw RuntimeException( msg, Reference< XInterface >() );
76 //--------------------------------------------------------------------------------------------------
77 static inline bool isXInterface( rtl_uString * pStr ) SAL_THROW( () )
79 return (((OUString const *)&pStr)->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) != sal_False);
81 //--------------------------------------------------------------------------------------------------
82 static inline void * makeInterface( sal_IntPtr nOffset, void * that ) SAL_THROW( () )
84 return (((char *)that) + nOffset);
86 //--------------------------------------------------------------------------------------------------
87 static inline bool __td_equals(
88 typelib_TypeDescriptionReference const * pTDR1,
89 typelib_TypeDescriptionReference const * pTDR2 )
90 SAL_THROW( () )
92 return ((pTDR1 == pTDR2) ||
93 ((OUString const *)&pTDR1->pTypeName)->equals( *(OUString const *)&pTDR2->pTypeName ) != sal_False);
95 //--------------------------------------------------------------------------------------------------
96 static inline type_entry * __getTypeEntries( class_data * cd )
97 SAL_THROW( (RuntimeException) )
99 type_entry * pEntries = cd->m_typeEntries;
100 if (! cd->m_storedTypeRefs) // not inited?
102 MutexGuard guard( getImplHelperInitMutex() );
103 if (! cd->m_storedTypeRefs) // not inited?
105 // get all types
106 for ( sal_Int32 n = cd->m_nTypes; n--; )
108 type_entry * pEntry = &pEntries[ n ];
109 Type const & rType = (*pEntry->m_type.getCppuType)( 0 );
110 OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
111 OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
112 if (rType.getTypeClass() != TypeClass_INTERFACE)
114 OUStringBuffer buf( 48 );
115 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("type \"") );
116 buf.append( rType.getTypeName() );
117 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" is no interface type!") );
118 OUString msg( buf.makeStringAndClear() );
119 #if OSL_DEBUG_LEVEL > 0
120 OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
121 OSL_ENSURE( 0, str.getStr() );
122 #endif
123 throw RuntimeException( msg, Reference< XInterface >() );
125 // ref is statically held by getCppuType()
126 pEntry->m_type.typeRef = rType.getTypeLibType();
128 cd->m_storedTypeRefs = sal_True;
131 return pEntries;
133 //--------------------------------------------------------------------------------------------------
134 static inline void __fillTypes( Type * types, class_data * cd )
135 SAL_THROW( (RuntimeException) )
137 type_entry * pEntries = __getTypeEntries( cd );
138 for ( sal_Int32 n = cd->m_nTypes; n--; )
140 types[ n ] = pEntries[ n ].m_type.typeRef;
143 //--------------------------------------------------------------------------------------------------
144 namespace {
146 bool recursivelyFindType(
147 typelib_TypeDescriptionReference const * demandedType,
148 typelib_InterfaceTypeDescription const * type, sal_IntPtr * offset)
150 // This code assumes that the vtables of a multiple-inheritance class (the
151 // offset amount by which to adjust the this pointer) follow one another in
152 // the object layout, and that they contain slots for the inherited classes
153 // in a specifc order. In theory, that need not hold for any given
154 // platform; in practice, it seems to work well on all supported platforms:
155 next:
156 for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
157 if (i > 0) {
158 *offset += sizeof (void *);
160 typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
161 // ignore XInterface:
162 if (base->nBaseTypes > 0) {
163 if (__td_equals(
164 reinterpret_cast<
165 typelib_TypeDescriptionReference const * >(base),
166 demandedType))
168 return true;
170 // Profiling showed that it is important to speed up the common case
171 // of only one base:
172 if (type->nBaseTypes == 1) {
173 type = base;
174 goto next;
176 if (recursivelyFindType(demandedType, base, offset)) {
177 return true;
181 return false;
186 static inline void * __queryDeepNoXInterface(
187 typelib_TypeDescriptionReference * pDemandedTDR, class_data * cd, void * that )
188 SAL_THROW( (RuntimeException) )
190 type_entry * pEntries = __getTypeEntries( cd );
191 sal_Int32 nTypes = cd->m_nTypes;
192 sal_Int32 n;
194 // try top interfaces without getting td
195 for ( n = 0; n < nTypes; ++n )
197 if (__td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
199 return makeInterface( pEntries[ n ].m_offset, that );
202 // query deep getting td
203 for ( n = 0; n < nTypes; ++n )
205 typelib_TypeDescription * pTD = 0;
206 TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
207 if (pTD)
209 // exclude top (already tested) and bottom (XInterface) interface
210 OSL_ENSURE(
211 reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
212 nBaseTypes > 0,
213 "### want to implement XInterface:"
214 " template argument is XInterface?!?!?!" );
215 sal_IntPtr offset = pEntries[n].m_offset;
216 bool found = recursivelyFindType(
217 pDemandedTDR,
218 reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
219 &offset);
220 TYPELIB_DANGER_RELEASE( pTD );
221 if (found) {
222 return makeInterface( offset, that );
225 else
227 OUStringBuffer buf( 64 );
228 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot get type description for type \"") );
229 buf.append( pEntries[ n ].m_type.typeRef->pTypeName );
230 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
231 OUString msg( buf.makeStringAndClear() );
232 #if OSL_DEBUG_LEVEL > 0
233 OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
234 OSL_ENSURE( 0, str.getStr() );
235 #endif
236 throw RuntimeException( msg, Reference< XInterface >() );
239 return 0;
242 // ImplHelper
243 //==================================================================================================
244 Any SAL_CALL ImplHelper_query(
245 Type const & rType, class_data * cd, void * that )
246 SAL_THROW( (RuntimeException) )
248 checkInterface( rType );
249 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
251 void * p;
252 // shortcut for XInterface
253 if (isXInterface( pTDR->pTypeName ))
255 // take first one
256 p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
258 else
260 p = __queryDeepNoXInterface( pTDR, cd, that );
261 if (! p)
263 return Any();
266 return Any( &p, pTDR );
268 //==================================================================================================
269 Any SAL_CALL ImplHelper_queryNoXInterface(
270 Type const & rType, class_data * cd, void * that )
271 SAL_THROW( (RuntimeException) )
273 checkInterface( rType );
274 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
276 void * p = __queryDeepNoXInterface( pTDR, cd, that );
277 if (p)
279 return Any( &p, pTDR );
281 else
283 return Any();
286 //==================================================================================================
287 Sequence< sal_Int8 > SAL_CALL ImplHelper_getImplementationId( class_data * cd )
288 SAL_THROW( (RuntimeException) )
290 if (! cd->m_createdId)
292 sal_uInt8 * id = (sal_uInt8 *)alloca( 16 );
293 ::rtl_createUuid( (sal_uInt8 *)id, 0, sal_True );
295 MutexGuard guard( getImplHelperInitMutex() );
296 if (! cd->m_createdId)
298 memcpy( cd->m_id, id, 16 );
299 cd->m_createdId = sal_True;
303 sal_Sequence * seq = 0;
304 ::rtl_byte_sequence_constructFromArray( &seq, cd->m_id, 16 );
305 return Sequence< sal_Int8 >( seq, SAL_NO_ACQUIRE );
307 //==================================================================================================
308 Sequence< Type > SAL_CALL ImplHelper_getTypes(
309 class_data * cd )
310 SAL_THROW( (RuntimeException) )
312 Sequence< Type > types( cd->m_nTypes );
313 Type * pTypes = types.getArray();
314 __fillTypes( pTypes, cd );
315 return types;
317 //==================================================================================================
318 Sequence< Type > SAL_CALL ImplInhHelper_getTypes(
319 class_data * cd, Sequence< Type > const & rAddTypes )
320 SAL_THROW( (RuntimeException) )
322 sal_Int32 nImplTypes = cd->m_nTypes;
323 sal_Int32 nAddTypes = rAddTypes.getLength();
324 Sequence< Type > types( nImplTypes + nAddTypes );
325 Type * pTypes = types.getArray();
326 __fillTypes( pTypes, cd );
327 // append base types
328 Type const * pAddTypes = rAddTypes.getConstArray();
329 while (nAddTypes--)
331 pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ];
333 return types;
336 // WeakImplHelper
337 //==================================================================================================
338 Any SAL_CALL WeakImplHelper_query(
339 Type const & rType, class_data * cd, void * that, OWeakObject * pBase )
340 SAL_THROW( (RuntimeException) )
342 checkInterface( rType );
343 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
345 // shortcut XInterface to OWeakObject
346 if (! isXInterface( pTDR->pTypeName ))
348 void * p = __queryDeepNoXInterface( pTDR, cd, that );
349 if (p)
351 return Any( &p, pTDR );
354 return pBase->OWeakObject::queryInterface( rType );
356 //==================================================================================================
357 Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
358 class_data * cd )
359 SAL_THROW( (RuntimeException) )
361 sal_Int32 nTypes = cd->m_nTypes;
362 Sequence< Type > types( nTypes +1 );
363 Type * pTypes = types.getArray();
364 __fillTypes( pTypes, cd );
365 pTypes[ nTypes ] = ::getCppuType( (Reference< XWeak > const *)0 );
366 return types;
369 // WeakAggImplHelper
370 //==================================================================================================
371 Any SAL_CALL WeakAggImplHelper_queryAgg(
372 Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase )
373 SAL_THROW( (RuntimeException) )
375 checkInterface( rType );
376 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
378 // shortcut XInterface to OWeakAggObject
379 if (! isXInterface( pTDR->pTypeName ))
381 void * p = __queryDeepNoXInterface( pTDR, cd, that );
382 if (p)
384 return Any( &p, pTDR );
387 return pBase->OWeakAggObject::queryAggregation( rType );
389 //==================================================================================================
390 Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
391 class_data * cd )
392 SAL_THROW( (RuntimeException) )
394 sal_Int32 nTypes = cd->m_nTypes;
395 Sequence< Type > types( nTypes +2 );
396 Type * pTypes = types.getArray();
397 __fillTypes( pTypes, cd );
398 pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
399 pTypes[ nTypes ] = ::getCppuType( (const Reference< XAggregation > *)0 );
400 return types;
403 // WeakComponentImplHelper
404 //==================================================================================================
405 Any SAL_CALL WeakComponentImplHelper_query(
406 Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase )
407 SAL_THROW( (RuntimeException) )
409 checkInterface( rType );
410 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
412 // shortcut XInterface to WeakComponentImplHelperBase
413 if (! isXInterface( pTDR->pTypeName ))
415 void * p = __queryDeepNoXInterface( pTDR, cd, that );
416 if (p)
418 return Any( &p, pTDR );
421 return pBase->WeakComponentImplHelperBase::queryInterface( rType );
423 //==================================================================================================
424 Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
425 class_data * cd )
426 SAL_THROW( (RuntimeException) )
428 sal_Int32 nTypes = cd->m_nTypes;
429 Sequence< Type > types( nTypes +2 );
430 Type * pTypes = types.getArray();
431 __fillTypes( pTypes, cd );
432 pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
433 pTypes[ nTypes ] = ::getCppuType( (Reference< lang::XComponent > const *)0 );
434 return types;
437 // WeakAggComponentImplHelper
438 //==================================================================================================
439 Any SAL_CALL WeakAggComponentImplHelper_queryAgg(
440 Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase )
441 SAL_THROW( (RuntimeException) )
443 checkInterface( rType );
444 typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
446 // shortcut XInterface to WeakAggComponentImplHelperBase
447 if (! isXInterface( pTDR->pTypeName ))
449 void * p = __queryDeepNoXInterface( pTDR, cd, that );
450 if (p)
452 return Any( &p, pTDR );
455 return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
457 //==================================================================================================
458 Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
459 class_data * cd )
460 SAL_THROW( (RuntimeException) )
462 sal_Int32 nTypes = cd->m_nTypes;
463 Sequence< Type > types( nTypes +3 );
464 Type * pTypes = types.getArray();
465 __fillTypes( pTypes, cd );
466 pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
467 pTypes[ nTypes++ ] = ::getCppuType( (const Reference< XAggregation > *)0 );
468 pTypes[ nTypes ] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
469 return types;