1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: implbase_ex.cxx,v $
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>
36 #include <osl/diagnose.h>
37 #include <rtl/byteseq.hxx>
38 #include <rtl/ustrbuf.hxx>
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
;
53 /** Shared mutex for implementation helper initialization.
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() );
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
)
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?
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() );
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
;
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 //--------------------------------------------------------------------------------------------------
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:
156 for (sal_Int32 i
= 0; i
< type
->nBaseTypes
; ++i
) {
158 *offset
+= sizeof (void *);
160 typelib_InterfaceTypeDescription
const * base
= type
->ppBaseTypes
[i
];
161 // ignore XInterface:
162 if (base
->nBaseTypes
> 0) {
165 typelib_TypeDescriptionReference
const * >(base
),
170 // Profiling showed that it is important to speed up the common case
172 if (type
->nBaseTypes
== 1) {
176 if (recursivelyFindType(demandedType
, base
, offset
)) {
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
;
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
);
209 // exclude top (already tested) and bottom (XInterface) interface
211 reinterpret_cast< typelib_InterfaceTypeDescription
* >(pTD
)->
213 "### want to implement XInterface:"
214 " template argument is XInterface?!?!?!" );
215 sal_IntPtr offset
= pEntries
[n
].m_offset
;
216 bool found
= recursivelyFindType(
218 reinterpret_cast< typelib_InterfaceTypeDescription
* >(pTD
),
220 TYPELIB_DANGER_RELEASE( pTD
);
222 return makeInterface( offset
, that
);
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() );
236 throw RuntimeException( msg
, Reference
< XInterface
>() );
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();
252 // shortcut for XInterface
253 if (isXInterface( pTDR
->pTypeName
))
256 p
= makeInterface( cd
->m_typeEntries
[ 0 ].m_offset
, that
);
260 p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
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
);
279 return Any( &p
, pTDR
);
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(
310 SAL_THROW( (RuntimeException
) )
312 Sequence
< Type
> types( cd
->m_nTypes
);
313 Type
* pTypes
= types
.getArray();
314 __fillTypes( pTypes
, cd
);
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
);
328 Type
const * pAddTypes
= rAddTypes
.getConstArray();
331 pTypes
[ nImplTypes
+ nAddTypes
] = pAddTypes
[ nAddTypes
];
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
);
351 return Any( &p
, pTDR
);
354 return pBase
->OWeakObject::queryInterface( rType
);
356 //==================================================================================================
357 Sequence
< Type
> SAL_CALL
WeakImplHelper_getTypes(
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 );
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
);
384 return Any( &p
, pTDR
);
387 return pBase
->OWeakAggObject::queryAggregation( rType
);
389 //==================================================================================================
390 Sequence
< Type
> SAL_CALL
WeakAggImplHelper_getTypes(
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 );
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
);
418 return Any( &p
, pTDR
);
421 return pBase
->WeakComponentImplHelperBase::queryInterface( rType
);
423 //==================================================================================================
424 Sequence
< Type
> SAL_CALL
WeakComponentImplHelper_getTypes(
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 );
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
);
452 return Any( &p
, pTDR
);
455 return pBase
->WeakAggComponentImplHelperBase::queryAggregation( rType
);
457 //==================================================================================================
458 Sequence
< Type
> SAL_CALL
WeakAggComponentImplHelper_getTypes(
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 );