Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
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.
15 : : *
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).
21 : : *
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.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <sal/alloca.h>
30 : :
31 : : #include <string.h>
32 : : #include <osl/diagnose.h>
33 : : #include <rtl/byteseq.hxx>
34 : : #include <rtl/ustrbuf.hxx>
35 : : #include <rtl/uuid.h>
36 : : #include <cppuhelper/compbase_ex.hxx>
37 : :
38 : : #include "com/sun/star/uno/RuntimeException.hpp"
39 : :
40 : : using namespace ::cppu;
41 : : using namespace ::osl;
42 : : using namespace ::rtl;
43 : : using namespace ::com::sun::star;
44 : : using namespace ::com::sun::star::uno;
45 : :
46 : : namespace cppu
47 : : {
48 : :
49 : : /** Shared mutex for implementation helper initialization.
50 : : Not for public use.
51 : : */
52 : : ::osl::Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW(());
53 : :
54 : : //--------------------------------------------------------------------------------------------------
55 : 17216596 : static inline void checkInterface( Type const & rType )
56 : : SAL_THROW( (RuntimeException) )
57 : : {
58 [ - + ]: 17216596 : if (TypeClass_INTERFACE != rType.getTypeClass())
59 : : {
60 : 0 : OUStringBuffer buf( 64 );
61 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("querying for interface \"") );
62 [ # # ]: 0 : buf.append( rType.getTypeName() );
63 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": no interface type!") );
64 [ # # ]: 0 : OUString msg( buf.makeStringAndClear() );
65 : : #if OSL_DEBUG_LEVEL > 0
66 : : OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
67 : : OSL_FAIL( str.getStr() );
68 : : #endif
69 [ # # ]: 0 : throw RuntimeException( msg, Reference< XInterface >() );
70 : : }
71 : 17216579 : }
72 : : //--------------------------------------------------------------------------------------------------
73 : 12857129 : static inline bool isXInterface( rtl_uString * pStr ) SAL_THROW(())
74 : : {
75 : 12857129 : return (*((OUString const *)&pStr) == "com.sun.star.uno.XInterface");
76 : : }
77 : : //--------------------------------------------------------------------------------------------------
78 : 10296494 : static inline void * makeInterface( sal_IntPtr nOffset, void * that ) SAL_THROW(())
79 : : {
80 : 10296494 : return (((char *)that) + nOffset);
81 : : }
82 : : //--------------------------------------------------------------------------------------------------
83 : 108932382 : static inline bool __td_equals(
84 : : typelib_TypeDescriptionReference const * pTDR1,
85 : : typelib_TypeDescriptionReference const * pTDR2 )
86 : : SAL_THROW(())
87 : : {
88 : : return ((pTDR1 == pTDR2) ||
89 [ + + ][ + ]: 108932382 : ((OUString const *)&pTDR1->pTypeName)->equals( *(OUString const *)&pTDR2->pTypeName ) != sal_False);
90 : : }
91 : : //--------------------------------------------------------------------------------------------------
92 : 16139128 : static inline type_entry * __getTypeEntries( class_data * cd )
93 : : SAL_THROW( (RuntimeException) )
94 : : {
95 : 16139128 : type_entry * pEntries = cd->m_typeEntries;
96 [ + + ]: 16139128 : if (! cd->m_storedTypeRefs) // not inited?
97 : : {
98 [ + - ][ + - ]: 41889 : MutexGuard guard( getImplHelperInitMutex() );
99 [ + - ]: 41889 : if (! cd->m_storedTypeRefs) // not inited?
100 : : {
101 : : // get all types
102 [ + + ]: 209303 : for ( sal_Int32 n = cd->m_nTypes; n--; )
103 : : {
104 : 167414 : type_entry * pEntry = &pEntries[ n ];
105 [ + - ]: 167414 : Type const & rType = (*pEntry->m_type.getCppuType)( 0 );
106 : : OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
107 : : OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
108 [ - + ]: 167414 : if (rType.getTypeClass() != TypeClass_INTERFACE)
109 : : {
110 : 0 : OUStringBuffer buf( 48 );
111 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("type \"") );
112 [ # # ]: 0 : buf.append( rType.getTypeName() );
113 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" is no interface type!") );
114 [ # # ]: 0 : OUString msg( buf.makeStringAndClear() );
115 : : #if OSL_DEBUG_LEVEL > 0
116 : : OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
117 : : OSL_FAIL( str.getStr() );
118 : : #endif
119 [ # # ]: 0 : throw RuntimeException( msg, Reference< XInterface >() );
120 : : }
121 : : // ref is statically held by getCppuType()
122 : 167414 : pEntry->m_type.typeRef = rType.getTypeLibType();
123 : : }
124 : 41889 : cd->m_storedTypeRefs = sal_True;
125 [ + - ]: 41889 : }
126 : : }
127 : 16139128 : return pEntries;
128 : : }
129 : : //--------------------------------------------------------------------------------------------------
130 : 8193 : static inline void __fillTypes( Type * types, class_data * cd )
131 : : SAL_THROW( (RuntimeException) )
132 : : {
133 : 8193 : type_entry * pEntries = __getTypeEntries( cd );
134 [ + + ]: 142761 : for ( sal_Int32 n = cd->m_nTypes; n--; )
135 : : {
136 : 134568 : types[ n ] = pEntries[ n ].m_type.typeRef;
137 : : }
138 : 8193 : }
139 : : //--------------------------------------------------------------------------------------------------
140 : : namespace {
141 : :
142 : 61811400 : bool recursivelyFindType(
143 : : typelib_TypeDescriptionReference const * demandedType,
144 : : typelib_InterfaceTypeDescription const * type, sal_IntPtr * offset)
145 : : {
146 : : // This code assumes that the vtables of a multiple-inheritance class (the
147 : : // offset amount by which to adjust the this pointer) follow one another in
148 : : // the object layout, and that they contain slots for the inherited classes
149 : : // in a specifc order. In theory, that need not hold for any given
150 : : // platform; in practice, it seems to work well on all supported platforms:
151 : : next:
152 [ + + ]: 111992557 : for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
153 [ + + ]: 62235663 : if (i > 0) {
154 : 424273 : *offset += sizeof (void *);
155 : : }
156 : 62235663 : typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
157 : : // ignore XInterface:
158 [ + + ]: 62235663 : if (base->nBaseTypes > 0) {
159 [ + + ]: 12803852 : if (__td_equals(
160 : : reinterpret_cast<
161 : : typelib_TypeDescriptionReference const * >(base),
162 : : demandedType))
163 : : {
164 : 1939447 : return true;
165 : : }
166 : : // Profiling showed that it is important to speed up the common case
167 : : // of only one base:
168 [ + + ]: 10864599 : if (type->nBaseTypes == 1) {
169 : 10090493 : type = base;
170 : 10090493 : goto next;
171 : : }
172 [ + + ]: 774106 : if (recursivelyFindType(demandedType, base, offset)) {
173 : 24760 : return true;
174 : : }
175 : : }
176 : : }
177 : 51721101 : return false;
178 : : }
179 : :
180 : : }
181 : :
182 : 16130939 : static inline void * __queryDeepNoXInterface(
183 : : typelib_TypeDescriptionReference * pDemandedTDR, class_data * cd, void * that )
184 : : SAL_THROW( (RuntimeException) )
185 : : {
186 : 16130939 : type_entry * pEntries = __getTypeEntries( cd );
187 : 16129294 : sal_Int32 nTypes = cd->m_nTypes;
188 : : sal_Int32 n;
189 : :
190 : : // try top interfaces without getting td
191 [ + + ]: 103973060 : for ( n = 0; n < nTypes; ++n )
192 : : {
193 [ + + ]: 96126753 : if (__td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
194 : : {
195 : 8284621 : return makeInterface( pEntries[ n ].m_offset, that );
196 : : }
197 : : }
198 : : // query deep getting td
199 [ + + ]: 56853854 : for ( n = 0; n < nTypes; ++n )
200 : : {
201 : 50946978 : typelib_TypeDescription * pTD = 0;
202 [ + ][ + ][ + ]: 50946978 : TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
[ + + ][ + - ]
203 [ + - ]: 50946985 : if (pTD)
204 : : {
205 : : // exclude top (already tested) and bottom (XInterface) interface
206 : : OSL_ENSURE(
207 : : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
208 : : nBaseTypes > 0,
209 : : "### want to implement XInterface:"
210 : : " template argument is XInterface?!?!?!" );
211 : 50946985 : sal_IntPtr offset = pEntries[n].m_offset;
212 : : bool found = recursivelyFindType(
213 : : pDemandedTDR,
214 : : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
215 [ + - ]: 50946985 : &offset);
216 [ + + ][ + ]: 50946972 : TYPELIB_DANGER_RELEASE( pTD );
217 [ + + ]: 50946994 : if (found) {
218 : 1939447 : return makeInterface( offset, that );
219 : : }
220 : : }
221 : : else
222 : : {
223 : 0 : OUStringBuffer buf( 64 );
224 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot get type description for type \"") );
225 [ # # ]: 0 : buf.append( pEntries[ n ].m_type.typeRef->pTypeName );
226 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
227 [ # # ]: 0 : OUString msg( buf.makeStringAndClear() );
228 : : #if OSL_DEBUG_LEVEL > 0
229 : : OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
230 : : OSL_FAIL( str.getStr() );
231 : : #endif
232 [ # # ]: 0 : throw RuntimeException( msg, Reference< XInterface >() );
233 : : }
234 : : }
235 : 16130945 : return 0;
236 : : }
237 : :
238 : : // ImplHelper
239 : : //==================================================================================================
240 : 1122104 : Any SAL_CALL ImplHelper_query(
241 : : Type const & rType, class_data * cd, void * that )
242 : : SAL_THROW( (RuntimeException) )
243 : : {
244 [ + - ]: 1122104 : checkInterface( rType );
245 : 1122104 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
246 : :
247 : : void * p;
248 : : // shortcut for XInterface
249 [ + + ][ + - ]: 1122104 : if (isXInterface( pTDR->pTypeName ))
250 : : {
251 : : // take first one
252 : 72427 : p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
253 : : }
254 : : else
255 : : {
256 [ + - ]: 1049677 : p = __queryDeepNoXInterface( pTDR, cd, that );
257 [ + + ]: 1049677 : if (! p)
258 : : {
259 : 916811 : return Any();
260 : : }
261 : : }
262 : 1122104 : return Any( &p, pTDR );
263 : : }
264 : : //==================================================================================================
265 : 4359469 : Any SAL_CALL ImplHelper_queryNoXInterface(
266 : : Type const & rType, class_data * cd, void * that )
267 : : SAL_THROW( (RuntimeException) )
268 : : {
269 [ + - ]: 4359469 : checkInterface( rType );
270 : 4359471 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
271 : :
272 [ + - ]: 4359471 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
273 [ + + ]: 4359471 : if (p)
274 : : {
275 : 1964196 : return Any( &p, pTDR );
276 : : }
277 : : else
278 : : {
279 : 4359471 : return Any();
280 : : }
281 : : }
282 : : //==================================================================================================
283 : 4311 : Sequence< sal_Int8 > SAL_CALL ImplHelper_getImplementationId( class_data * cd )
284 : : SAL_THROW( (RuntimeException) )
285 : : {
286 [ + + ]: 4311 : if (! cd->m_createdId)
287 : : {
288 : 1093 : sal_uInt8 * id = (sal_uInt8 *)alloca( 16 );
289 [ + - ]: 1093 : ::rtl_createUuid( (sal_uInt8 *)id, 0, sal_True );
290 : :
291 [ + - ][ + - ]: 1093 : MutexGuard guard( getImplHelperInitMutex() );
292 [ + - ]: 1093 : if (! cd->m_createdId)
293 : : {
294 : 1093 : memcpy( cd->m_id, id, 16 );
295 : 1093 : cd->m_createdId = sal_True;
296 [ + - ]: 1093 : }
297 : : }
298 : :
299 : 4311 : sal_Sequence * seq = 0;
300 : 4311 : ::rtl_byte_sequence_constructFromArray( &seq, cd->m_id, 16 );
301 : 4311 : return Sequence< sal_Int8 >( seq, SAL_NO_ACQUIRE );
302 : : }
303 : : //==================================================================================================
304 : 522 : Sequence< Type > SAL_CALL ImplHelper_getTypes(
305 : : class_data * cd )
306 : : SAL_THROW( (RuntimeException) )
307 : : {
308 : 522 : Sequence< Type > types( cd->m_nTypes );
309 [ + - ]: 522 : Type * pTypes = types.getArray();
310 [ + - ]: 522 : __fillTypes( pTypes, cd );
311 : 522 : return types;
312 : : }
313 : : //==================================================================================================
314 : 92 : Sequence< Type > SAL_CALL ImplInhHelper_getTypes(
315 : : class_data * cd, Sequence< Type > const & rAddTypes )
316 : : SAL_THROW( (RuntimeException) )
317 : : {
318 : 92 : sal_Int32 nImplTypes = cd->m_nTypes;
319 : 92 : sal_Int32 nAddTypes = rAddTypes.getLength();
320 : 92 : Sequence< Type > types( nImplTypes + nAddTypes );
321 [ + - ]: 92 : Type * pTypes = types.getArray();
322 [ + - ]: 92 : __fillTypes( pTypes, cd );
323 : : // append base types
324 : 92 : Type const * pAddTypes = rAddTypes.getConstArray();
325 [ + + ]: 1066 : while (nAddTypes--)
326 : : {
327 : 974 : pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ];
328 : : }
329 : 92 : return types;
330 : : }
331 : :
332 : : // WeakImplHelper
333 : : //==================================================================================================
334 : 7784975 : Any SAL_CALL WeakImplHelper_query(
335 : : Type const & rType, class_data * cd, void * that, OWeakObject * pBase )
336 : : SAL_THROW( (RuntimeException) )
337 : : {
338 : 7784975 : checkInterface( rType );
339 : 7784974 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
340 : :
341 : : // shortcut XInterface to OWeakObject
342 [ + + ]: 7784974 : if (! isXInterface( pTDR->pTypeName ))
343 : : {
344 [ + - ]: 6951022 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
345 [ + + ]: 6951021 : if (p)
346 : : {
347 : 6951021 : return Any( &p, pTDR );
348 : : }
349 : : }
350 : 7784975 : return pBase->OWeakObject::queryInterface( rType );
351 : : }
352 : : //==================================================================================================
353 : 4545 : Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
354 : : class_data * cd )
355 : : SAL_THROW( (RuntimeException) )
356 : : {
357 : 4545 : sal_Int32 nTypes = cd->m_nTypes;
358 : 4545 : Sequence< Type > types( nTypes +1 );
359 [ + - ]: 4545 : Type * pTypes = types.getArray();
360 [ + - ]: 4545 : __fillTypes( pTypes, cd );
361 [ + - ]: 4545 : pTypes[ nTypes ] = ::getCppuType( (Reference< XWeak > const *)0 );
362 : 4545 : return types;
363 : : }
364 : :
365 : : // WeakAggImplHelper
366 : : //==================================================================================================
367 : 1624216 : Any SAL_CALL WeakAggImplHelper_queryAgg(
368 : : Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase )
369 : : SAL_THROW( (RuntimeException) )
370 : : {
371 : 1624216 : checkInterface( rType );
372 : 1624216 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
373 : :
374 : : // shortcut XInterface to OWeakAggObject
375 [ + + ]: 1624216 : if (! isXInterface( pTDR->pTypeName ))
376 : : {
377 [ + - ]: 1536727 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
378 [ + + ]: 1536727 : if (p)
379 : : {
380 : 1536727 : return Any( &p, pTDR );
381 : : }
382 : : }
383 : 1624216 : return pBase->OWeakAggObject::queryAggregation( rType );
384 : : }
385 : : //==================================================================================================
386 : 1844 : Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
387 : : class_data * cd )
388 : : SAL_THROW( (RuntimeException) )
389 : : {
390 : 1844 : sal_Int32 nTypes = cd->m_nTypes;
391 : 1844 : Sequence< Type > types( nTypes +2 );
392 [ + - ]: 1844 : Type * pTypes = types.getArray();
393 [ + - ]: 1844 : __fillTypes( pTypes, cd );
394 [ + - ]: 1844 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
395 [ + - ]: 1844 : pTypes[ nTypes ] = ::getCppuType( (const Reference< XAggregation > *)0 );
396 : 1844 : return types;
397 : : }
398 : :
399 : : // WeakComponentImplHelper
400 : : //==================================================================================================
401 : 2281050 : Any SAL_CALL WeakComponentImplHelper_query(
402 : : Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase )
403 : : SAL_THROW( (RuntimeException) )
404 : : {
405 : 2281050 : checkInterface( rType );
406 : 2281050 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
407 : :
408 : : // shortcut XInterface to WeakComponentImplHelperBase
409 [ + + ]: 2281050 : if (! isXInterface( pTDR->pTypeName ))
410 : : {
411 [ + - ]: 2206704 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
412 [ + + ]: 2206704 : if (p)
413 : : {
414 : 2206704 : return Any( &p, pTDR );
415 : : }
416 : : }
417 : 2281050 : return pBase->WeakComponentImplHelperBase::queryInterface( rType );
418 : : }
419 : : //==================================================================================================
420 : 1188 : Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
421 : : class_data * cd )
422 : : SAL_THROW( (RuntimeException) )
423 : : {
424 : 1188 : sal_Int32 nTypes = cd->m_nTypes;
425 : 1188 : Sequence< Type > types( nTypes +2 );
426 [ + - ]: 1188 : Type * pTypes = types.getArray();
427 [ + - ]: 1188 : __fillTypes( pTypes, cd );
428 [ + - ]: 1188 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
429 [ + - ]: 1188 : pTypes[ nTypes ] = ::getCppuType( (Reference< lang::XComponent > const *)0 );
430 : 1188 : return types;
431 : : }
432 : :
433 : : // WeakAggComponentImplHelper
434 : : //==================================================================================================
435 : 44788 : Any SAL_CALL WeakAggComponentImplHelper_queryAgg(
436 : : Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase )
437 : : SAL_THROW( (RuntimeException) )
438 : : {
439 : 44788 : checkInterface( rType );
440 : 44788 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
441 : :
442 : : // shortcut XInterface to WeakAggComponentImplHelperBase
443 [ + + ]: 44788 : if (! isXInterface( pTDR->pTypeName ))
444 : : {
445 [ + - ]: 27343 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
446 [ + + ]: 27343 : if (p)
447 : : {
448 : 27343 : return Any( &p, pTDR );
449 : : }
450 : : }
451 : 44788 : return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
452 : : }
453 : : //==================================================================================================
454 : 2 : Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
455 : : class_data * cd )
456 : : SAL_THROW( (RuntimeException) )
457 : : {
458 : 2 : sal_Int32 nTypes = cd->m_nTypes;
459 : 2 : Sequence< Type > types( nTypes +3 );
460 [ + - ]: 2 : Type * pTypes = types.getArray();
461 [ + - ]: 2 : __fillTypes( pTypes, cd );
462 [ + - ]: 2 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
463 [ + - ]: 2 : pTypes[ nTypes++ ] = ::getCppuType( (const Reference< XAggregation > *)0 );
464 [ + - ]: 2 : pTypes[ nTypes ] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
465 : 2 : return types;
466 : : }
467 : :
468 : : }
469 : :
470 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|