1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_cppuhelper.hxx"
31 #include <sal/alloca.h>
34 #include <osl/diagnose.h>
35 #include <rtl/byteseq.hxx>
36 #include <rtl/ustrbuf.hxx>
38 #include <cppuhelper/compbase_ex.hxx>
40 #include "com/sun/star/uno/RuntimeException.hpp"
42 using namespace ::cppu
;
43 using namespace ::osl
;
44 using namespace ::rtl
;
45 using namespace ::com::sun::star
;
46 using namespace ::com::sun::star::uno
;
51 /** Shared mutex for implementation helper initialization.
54 ::osl::Mutex
& SAL_CALL
getImplHelperInitMutex(void) SAL_THROW( () );
56 //--------------------------------------------------------------------------------------------------
57 static inline void checkInterface( Type
const & rType
)
58 SAL_THROW( (RuntimeException
) )
60 if (TypeClass_INTERFACE
!= rType
.getTypeClass())
62 OUStringBuffer
buf( 64 );
63 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("querying for interface \"") );
64 buf
.append( rType
.getTypeName() );
65 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": no interface type!") );
66 OUString
msg( buf
.makeStringAndClear() );
67 #if OSL_DEBUG_LEVEL > 0
68 OString
str( OUStringToOString( msg
, RTL_TEXTENCODING_ASCII_US
) );
69 OSL_ENSURE( 0, str
.getStr() );
71 throw RuntimeException( msg
, Reference
< XInterface
>() );
74 //--------------------------------------------------------------------------------------------------
75 static inline bool isXInterface( rtl_uString
* pStr
) SAL_THROW( () )
77 return (((OUString
const *)&pStr
)->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) != sal_False
);
79 //--------------------------------------------------------------------------------------------------
80 static inline void * makeInterface( sal_IntPtr nOffset
, void * that
) SAL_THROW( () )
82 return (((char *)that
) + nOffset
);
84 //--------------------------------------------------------------------------------------------------
85 static inline bool __td_equals(
86 typelib_TypeDescriptionReference
const * pTDR1
,
87 typelib_TypeDescriptionReference
const * pTDR2
)
90 return ((pTDR1
== pTDR2
) ||
91 ((OUString
const *)&pTDR1
->pTypeName
)->equals( *(OUString
const *)&pTDR2
->pTypeName
) != sal_False
);
93 //--------------------------------------------------------------------------------------------------
94 static inline type_entry
* __getTypeEntries( class_data
* cd
)
95 SAL_THROW( (RuntimeException
) )
97 type_entry
* pEntries
= cd
->m_typeEntries
;
98 if (! cd
->m_storedTypeRefs
) // not inited?
100 MutexGuard
guard( getImplHelperInitMutex() );
101 if (! cd
->m_storedTypeRefs
) // not inited?
104 for ( sal_Int32 n
= cd
->m_nTypes
; n
--; )
106 type_entry
* pEntry
= &pEntries
[ n
];
107 Type
const & rType
= (*pEntry
->m_type
.getCppuType
)( 0 );
108 OSL_ENSURE( rType
.getTypeClass() == TypeClass_INTERFACE
, "### wrong helper init: expected interface!" );
109 OSL_ENSURE( ! isXInterface( rType
.getTypeLibType()->pTypeName
), "### want to implement XInterface: template argument is XInterface?!?!?!" );
110 if (rType
.getTypeClass() != TypeClass_INTERFACE
)
112 OUStringBuffer
buf( 48 );
113 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("type \"") );
114 buf
.append( rType
.getTypeName() );
115 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" is no interface type!") );
116 OUString
msg( buf
.makeStringAndClear() );
117 #if OSL_DEBUG_LEVEL > 0
118 OString
str( OUStringToOString( msg
, RTL_TEXTENCODING_ASCII_US
) );
119 OSL_ENSURE( 0, str
.getStr() );
121 throw RuntimeException( msg
, Reference
< XInterface
>() );
123 // ref is statically held by getCppuType()
124 pEntry
->m_type
.typeRef
= rType
.getTypeLibType();
126 cd
->m_storedTypeRefs
= sal_True
;
131 //--------------------------------------------------------------------------------------------------
132 static inline void __fillTypes( Type
* types
, class_data
* cd
)
133 SAL_THROW( (RuntimeException
) )
135 type_entry
* pEntries
= __getTypeEntries( cd
);
136 for ( sal_Int32 n
= cd
->m_nTypes
; n
--; )
138 types
[ n
] = pEntries
[ n
].m_type
.typeRef
;
141 //--------------------------------------------------------------------------------------------------
144 bool recursivelyFindType(
145 typelib_TypeDescriptionReference
const * demandedType
,
146 typelib_InterfaceTypeDescription
const * type
, sal_IntPtr
* offset
)
148 // This code assumes that the vtables of a multiple-inheritance class (the
149 // offset amount by which to adjust the this pointer) follow one another in
150 // the object layout, and that they contain slots for the inherited classes
151 // in a specifc order. In theory, that need not hold for any given
152 // platform; in practice, it seems to work well on all supported platforms:
154 for (sal_Int32 i
= 0; i
< type
->nBaseTypes
; ++i
) {
156 *offset
+= sizeof (void *);
158 typelib_InterfaceTypeDescription
const * base
= type
->ppBaseTypes
[i
];
159 // ignore XInterface:
160 if (base
->nBaseTypes
> 0) {
163 typelib_TypeDescriptionReference
const * >(base
),
168 // Profiling showed that it is important to speed up the common case
170 if (type
->nBaseTypes
== 1) {
174 if (recursivelyFindType(demandedType
, base
, offset
)) {
184 static inline void * __queryDeepNoXInterface(
185 typelib_TypeDescriptionReference
* pDemandedTDR
, class_data
* cd
, void * that
)
186 SAL_THROW( (RuntimeException
) )
188 type_entry
* pEntries
= __getTypeEntries( cd
);
189 sal_Int32 nTypes
= cd
->m_nTypes
;
192 // try top interfaces without getting td
193 for ( n
= 0; n
< nTypes
; ++n
)
195 if (__td_equals( pEntries
[ n
].m_type
.typeRef
, pDemandedTDR
))
197 return makeInterface( pEntries
[ n
].m_offset
, that
);
200 // query deep getting td
201 for ( n
= 0; n
< nTypes
; ++n
)
203 typelib_TypeDescription
* pTD
= 0;
204 TYPELIB_DANGER_GET( &pTD
, pEntries
[ n
].m_type
.typeRef
);
207 // exclude top (already tested) and bottom (XInterface) interface
209 reinterpret_cast< typelib_InterfaceTypeDescription
* >(pTD
)->
211 "### want to implement XInterface:"
212 " template argument is XInterface?!?!?!" );
213 sal_IntPtr offset
= pEntries
[n
].m_offset
;
214 bool found
= recursivelyFindType(
216 reinterpret_cast< typelib_InterfaceTypeDescription
* >(pTD
),
218 TYPELIB_DANGER_RELEASE( pTD
);
220 return makeInterface( offset
, that
);
225 OUStringBuffer
buf( 64 );
226 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot get type description for type \"") );
227 buf
.append( pEntries
[ n
].m_type
.typeRef
->pTypeName
);
228 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
229 OUString
msg( buf
.makeStringAndClear() );
230 #if OSL_DEBUG_LEVEL > 0
231 OString
str( OUStringToOString( msg
, RTL_TEXTENCODING_ASCII_US
) );
232 OSL_ENSURE( 0, str
.getStr() );
234 throw RuntimeException( msg
, Reference
< XInterface
>() );
241 //==================================================================================================
242 Any SAL_CALL
ImplHelper_query(
243 Type
const & rType
, class_data
* cd
, void * that
)
244 SAL_THROW( (RuntimeException
) )
246 checkInterface( rType
);
247 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
250 // shortcut for XInterface
251 if (isXInterface( pTDR
->pTypeName
))
254 p
= makeInterface( cd
->m_typeEntries
[ 0 ].m_offset
, that
);
258 p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
264 return Any( &p
, pTDR
);
266 //==================================================================================================
267 Any SAL_CALL
ImplHelper_queryNoXInterface(
268 Type
const & rType
, class_data
* cd
, void * that
)
269 SAL_THROW( (RuntimeException
) )
271 checkInterface( rType
);
272 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
274 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
277 return Any( &p
, pTDR
);
284 //==================================================================================================
285 Sequence
< sal_Int8
> SAL_CALL
ImplHelper_getImplementationId( class_data
* cd
)
286 SAL_THROW( (RuntimeException
) )
288 if (! cd
->m_createdId
)
290 sal_uInt8
* id
= (sal_uInt8
*)alloca( 16 );
291 ::rtl_createUuid( (sal_uInt8
*)id
, 0, sal_True
);
293 MutexGuard
guard( getImplHelperInitMutex() );
294 if (! cd
->m_createdId
)
296 memcpy( cd
->m_id
, id
, 16 );
297 cd
->m_createdId
= sal_True
;
301 sal_Sequence
* seq
= 0;
302 ::rtl_byte_sequence_constructFromArray( &seq
, cd
->m_id
, 16 );
303 return Sequence
< sal_Int8
>( seq
, SAL_NO_ACQUIRE
);
305 //==================================================================================================
306 Sequence
< Type
> SAL_CALL
ImplHelper_getTypes(
308 SAL_THROW( (RuntimeException
) )
310 Sequence
< Type
> types( cd
->m_nTypes
);
311 Type
* pTypes
= types
.getArray();
312 __fillTypes( pTypes
, cd
);
315 //==================================================================================================
316 Sequence
< Type
> SAL_CALL
ImplInhHelper_getTypes(
317 class_data
* cd
, Sequence
< Type
> const & rAddTypes
)
318 SAL_THROW( (RuntimeException
) )
320 sal_Int32 nImplTypes
= cd
->m_nTypes
;
321 sal_Int32 nAddTypes
= rAddTypes
.getLength();
322 Sequence
< Type
> types( nImplTypes
+ nAddTypes
);
323 Type
* pTypes
= types
.getArray();
324 __fillTypes( pTypes
, cd
);
326 Type
const * pAddTypes
= rAddTypes
.getConstArray();
329 pTypes
[ nImplTypes
+ nAddTypes
] = pAddTypes
[ nAddTypes
];
335 //==================================================================================================
336 Any SAL_CALL
WeakImplHelper_query(
337 Type
const & rType
, class_data
* cd
, void * that
, OWeakObject
* pBase
)
338 SAL_THROW( (RuntimeException
) )
340 checkInterface( rType
);
341 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
343 // shortcut XInterface to OWeakObject
344 if (! isXInterface( pTDR
->pTypeName
))
346 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
349 return Any( &p
, pTDR
);
352 return pBase
->OWeakObject::queryInterface( rType
);
354 //==================================================================================================
355 Sequence
< Type
> SAL_CALL
WeakImplHelper_getTypes(
357 SAL_THROW( (RuntimeException
) )
359 sal_Int32 nTypes
= cd
->m_nTypes
;
360 Sequence
< Type
> types( nTypes
+1 );
361 Type
* pTypes
= types
.getArray();
362 __fillTypes( pTypes
, cd
);
363 pTypes
[ nTypes
] = ::getCppuType( (Reference
< XWeak
> const *)0 );
368 //==================================================================================================
369 Any SAL_CALL
WeakAggImplHelper_queryAgg(
370 Type
const & rType
, class_data
* cd
, void * that
, OWeakAggObject
* pBase
)
371 SAL_THROW( (RuntimeException
) )
373 checkInterface( rType
);
374 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
376 // shortcut XInterface to OWeakAggObject
377 if (! isXInterface( pTDR
->pTypeName
))
379 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
382 return Any( &p
, pTDR
);
385 return pBase
->OWeakAggObject::queryAggregation( rType
);
387 //==================================================================================================
388 Sequence
< Type
> SAL_CALL
WeakAggImplHelper_getTypes(
390 SAL_THROW( (RuntimeException
) )
392 sal_Int32 nTypes
= cd
->m_nTypes
;
393 Sequence
< Type
> types( nTypes
+2 );
394 Type
* pTypes
= types
.getArray();
395 __fillTypes( pTypes
, cd
);
396 pTypes
[ nTypes
++ ] = ::getCppuType( (Reference
< XWeak
> const *)0 );
397 pTypes
[ nTypes
] = ::getCppuType( (const Reference
< XAggregation
> *)0 );
401 // WeakComponentImplHelper
402 //==================================================================================================
403 Any SAL_CALL
WeakComponentImplHelper_query(
404 Type
const & rType
, class_data
* cd
, void * that
, WeakComponentImplHelperBase
* pBase
)
405 SAL_THROW( (RuntimeException
) )
407 checkInterface( rType
);
408 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
410 // shortcut XInterface to WeakComponentImplHelperBase
411 if (! isXInterface( pTDR
->pTypeName
))
413 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
416 return Any( &p
, pTDR
);
419 return pBase
->WeakComponentImplHelperBase::queryInterface( rType
);
421 //==================================================================================================
422 Sequence
< Type
> SAL_CALL
WeakComponentImplHelper_getTypes(
424 SAL_THROW( (RuntimeException
) )
426 sal_Int32 nTypes
= cd
->m_nTypes
;
427 Sequence
< Type
> types( nTypes
+2 );
428 Type
* pTypes
= types
.getArray();
429 __fillTypes( pTypes
, cd
);
430 pTypes
[ nTypes
++ ] = ::getCppuType( (Reference
< XWeak
> const *)0 );
431 pTypes
[ nTypes
] = ::getCppuType( (Reference
< lang::XComponent
> const *)0 );
435 // WeakAggComponentImplHelper
436 //==================================================================================================
437 Any SAL_CALL
WeakAggComponentImplHelper_queryAgg(
438 Type
const & rType
, class_data
* cd
, void * that
, WeakAggComponentImplHelperBase
* pBase
)
439 SAL_THROW( (RuntimeException
) )
441 checkInterface( rType
);
442 typelib_TypeDescriptionReference
* pTDR
= rType
.getTypeLibType();
444 // shortcut XInterface to WeakAggComponentImplHelperBase
445 if (! isXInterface( pTDR
->pTypeName
))
447 void * p
= __queryDeepNoXInterface( pTDR
, cd
, that
);
450 return Any( &p
, pTDR
);
453 return pBase
->WeakAggComponentImplHelperBase::queryAggregation( rType
);
455 //==================================================================================================
456 Sequence
< Type
> SAL_CALL
WeakAggComponentImplHelper_getTypes(
458 SAL_THROW( (RuntimeException
) )
460 sal_Int32 nTypes
= cd
->m_nTypes
;
461 Sequence
< Type
> types( nTypes
+3 );
462 Type
* pTypes
= types
.getArray();
463 __fillTypes( pTypes
, cd
);
464 pTypes
[ nTypes
++ ] = ::getCppuType( (Reference
< XWeak
> const *)0 );
465 pTypes
[ nTypes
++ ] = ::getCppuType( (const Reference
< XAggregation
> *)0 );
466 pTypes
[ nTypes
] = ::getCppuType( (const Reference
< lang::XComponent
> *)0 );
472 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */