Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/alloca.h>
21 :
22 : #include <string.h>
23 : #include <osl/diagnose.h>
24 : #include <rtl/byteseq.hxx>
25 : #include <rtl/ustrbuf.hxx>
26 : #include <rtl/uuid.h>
27 : #include <cppuhelper/compbase_ex.hxx>
28 :
29 : #include "com/sun/star/uno/RuntimeException.hpp"
30 :
31 : using namespace ::cppu;
32 : using namespace ::osl;
33 : using namespace ::rtl;
34 : using namespace ::com::sun::star;
35 : using namespace ::com::sun::star::uno;
36 :
37 : namespace cppu
38 : {
39 :
40 : /** Shared mutex for implementation helper initialization.
41 : Not for public use.
42 : */
43 : ::osl::Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW(());
44 :
45 : //--------------------------------------------------------------------------------------------------
46 1465392 : static inline void checkInterface( Type const & rType )
47 : SAL_THROW( (RuntimeException) )
48 : {
49 1465392 : if (TypeClass_INTERFACE != rType.getTypeClass())
50 : {
51 0 : OUStringBuffer buf( 64 );
52 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("querying for interface \"") );
53 0 : buf.append( rType.getTypeName() );
54 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": no interface type!") );
55 0 : OUString msg( buf.makeStringAndClear() );
56 : #if OSL_DEBUG_LEVEL > 0
57 : OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
58 : OSL_FAIL( str.getStr() );
59 : #endif
60 0 : throw RuntimeException( msg, Reference< XInterface >() );
61 : }
62 1465392 : }
63 : //--------------------------------------------------------------------------------------------------
64 1092334 : static inline bool isXInterface( rtl_uString * pStr ) SAL_THROW(())
65 : {
66 1092334 : return (*((OUString const *)&pStr) == "com.sun.star.uno.XInterface");
67 : }
68 : //--------------------------------------------------------------------------------------------------
69 936164 : static inline void * makeInterface( sal_IntPtr nOffset, void * that ) SAL_THROW(())
70 : {
71 936164 : return (((char *)that) + nOffset);
72 : }
73 : //--------------------------------------------------------------------------------------------------
74 9194222 : static inline bool __td_equals(
75 : typelib_TypeDescriptionReference const * pTDR1,
76 : typelib_TypeDescriptionReference const * pTDR2 )
77 : SAL_THROW(())
78 : {
79 : return ((pTDR1 == pTDR2) ||
80 9194222 : ((OUString const *)&pTDR1->pTypeName)->equals( *(OUString const *)&pTDR2->pTypeName ) != sal_False);
81 : }
82 : //--------------------------------------------------------------------------------------------------
83 1396591 : static inline type_entry * __getTypeEntries( class_data * cd )
84 : SAL_THROW( (RuntimeException) )
85 : {
86 1396591 : type_entry * pEntries = cd->m_typeEntries;
87 1396591 : if (! cd->m_storedTypeRefs) // not inited?
88 : {
89 4340 : MutexGuard guard( getImplHelperInitMutex() );
90 4340 : if (! cd->m_storedTypeRefs) // not inited?
91 : {
92 : // get all types
93 28172 : for ( sal_Int32 n = cd->m_nTypes; n--; )
94 : {
95 19492 : type_entry * pEntry = &pEntries[ n ];
96 19492 : Type const & rType = (*pEntry->m_type.getCppuType)( 0 );
97 : OSL_ENSURE( rType.getTypeClass() == TypeClass_INTERFACE, "### wrong helper init: expected interface!" );
98 : OSL_ENSURE( ! isXInterface( rType.getTypeLibType()->pTypeName ), "### want to implement XInterface: template argument is XInterface?!?!?!" );
99 19492 : if (rType.getTypeClass() != TypeClass_INTERFACE)
100 : {
101 0 : OUStringBuffer buf( 48 );
102 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("type \"") );
103 0 : buf.append( rType.getTypeName() );
104 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" is no interface type!") );
105 0 : OUString msg( buf.makeStringAndClear() );
106 : #if OSL_DEBUG_LEVEL > 0
107 : OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
108 : OSL_FAIL( str.getStr() );
109 : #endif
110 0 : throw RuntimeException( msg, Reference< XInterface >() );
111 : }
112 : // ref is statically held by getCppuType()
113 19492 : pEntry->m_type.typeRef = rType.getTypeLibType();
114 : }
115 4340 : cd->m_storedTypeRefs = sal_True;
116 4340 : }
117 : }
118 1396591 : return pEntries;
119 : }
120 : //--------------------------------------------------------------------------------------------------
121 667 : static inline void __fillTypes( Type * types, class_data * cd )
122 : SAL_THROW( (RuntimeException) )
123 : {
124 667 : type_entry * pEntries = __getTypeEntries( cd );
125 16788 : for ( sal_Int32 n = cd->m_nTypes; n--; )
126 : {
127 15454 : types[ n ] = pEntries[ n ].m_type.typeRef;
128 : }
129 667 : }
130 : //--------------------------------------------------------------------------------------------------
131 : namespace {
132 :
133 4928096 : bool recursivelyFindType(
134 : typelib_TypeDescriptionReference const * demandedType,
135 : typelib_InterfaceTypeDescription const * type, sal_IntPtr * offset)
136 : {
137 : // This code assumes that the vtables of a multiple-inheritance class (the
138 : // offset amount by which to adjust the this pointer) follow one another in
139 : // the object layout, and that they contain slots for the inherited classes
140 : // in a specifc order. In theory, that need not hold for any given
141 : // platform; in practice, it seems to work well on all supported platforms:
142 : next:
143 8985582 : for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) {
144 4984500 : if (i > 0) {
145 56404 : *offset += sizeof (void *);
146 : }
147 4984500 : typelib_InterfaceTypeDescription const * base = type->ppBaseTypes[i];
148 : // ignore XInterface:
149 4984500 : if (base->nBaseTypes > 0) {
150 1016765 : if (__td_equals(
151 : reinterpret_cast<
152 : typelib_TypeDescriptionReference const * >(base),
153 : demandedType))
154 : {
155 140863 : return true;
156 : }
157 : // Profiling showed that it is important to speed up the common case
158 : // of only one base:
159 875902 : if (type->nBaseTypes == 1) {
160 784154 : type = base;
161 784154 : goto next;
162 : }
163 91748 : if (recursivelyFindType(demandedType, base, offset)) {
164 1997 : return true;
165 : }
166 : }
167 : }
168 4001082 : return false;
169 : }
170 :
171 : }
172 :
173 1395924 : static inline void * __queryDeepNoXInterface(
174 : typelib_TypeDescriptionReference * pDemandedTDR, class_data * cd, void * that )
175 : SAL_THROW( (RuntimeException) )
176 : {
177 1395924 : type_entry * pEntries = __getTypeEntries( cd );
178 1395924 : sal_Int32 nTypes = cd->m_nTypes;
179 : sal_Int32 n;
180 :
181 : // try top interfaces without getting td
182 8780847 : for ( n = 0; n < nTypes; ++n )
183 : {
184 8177457 : if (__td_equals( pEntries[ n ].m_type.typeRef, pDemandedTDR ))
185 : {
186 792534 : return makeInterface( pEntries[ n ].m_offset, that );
187 : }
188 : }
189 : // query deep getting td
190 9029442 : for ( n = 0; n < nTypes; ++n )
191 : {
192 4052194 : typelib_TypeDescription * pTD = 0;
193 4052194 : TYPELIB_DANGER_GET( &pTD, pEntries[ n ].m_type.typeRef );
194 4052194 : if (pTD)
195 : {
196 : // exclude top (already tested) and bottom (XInterface) interface
197 : OSL_ENSURE(
198 : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD)->
199 : nBaseTypes > 0,
200 : "### want to implement XInterface:"
201 : " template argument is XInterface?!?!?!" );
202 4052194 : sal_IntPtr offset = pEntries[n].m_offset;
203 : bool found = recursivelyFindType(
204 : pDemandedTDR,
205 : reinterpret_cast< typelib_InterfaceTypeDescription * >(pTD),
206 4052194 : &offset);
207 4052194 : TYPELIB_DANGER_RELEASE( pTD );
208 4052194 : if (found) {
209 140863 : return makeInterface( offset, that );
210 : }
211 : }
212 : else
213 : {
214 0 : OUStringBuffer buf( 64 );
215 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot get type description for type \"") );
216 0 : buf.append( pEntries[ n ].m_type.typeRef->pTypeName );
217 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
218 0 : OUString msg( buf.makeStringAndClear() );
219 : #if OSL_DEBUG_LEVEL > 0
220 : OString str( OUStringToOString( msg, RTL_TEXTENCODING_ASCII_US ) );
221 : OSL_FAIL( str.getStr() );
222 : #endif
223 0 : throw RuntimeException( msg, Reference< XInterface >() );
224 : }
225 : }
226 462527 : return 0;
227 : }
228 :
229 : // ImplHelper
230 : //==================================================================================================
231 41101 : Any SAL_CALL ImplHelper_query(
232 : Type const & rType, class_data * cd, void * that )
233 : SAL_THROW( (RuntimeException) )
234 : {
235 41101 : checkInterface( rType );
236 41101 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
237 :
238 : void * p;
239 : // shortcut for XInterface
240 41101 : if (isXInterface( pTDR->pTypeName ))
241 : {
242 : // take first one
243 2767 : p = makeInterface( cd->m_typeEntries[ 0 ].m_offset, that );
244 : }
245 : else
246 : {
247 38334 : p = __queryDeepNoXInterface( pTDR, cd, that );
248 38334 : if (! p)
249 : {
250 34897 : return Any();
251 : }
252 : }
253 6204 : return Any( &p, pTDR );
254 : }
255 : //==================================================================================================
256 373058 : Any SAL_CALL ImplHelper_queryNoXInterface(
257 : Type const & rType, class_data * cd, void * that )
258 : SAL_THROW( (RuntimeException) )
259 : {
260 373058 : checkInterface( rType );
261 373058 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
262 :
263 373058 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
264 373058 : if (p)
265 : {
266 157584 : return Any( &p, pTDR );
267 : }
268 : else
269 : {
270 215474 : return Any();
271 : }
272 : }
273 : //==================================================================================================
274 364 : Sequence< sal_Int8 > SAL_CALL ImplHelper_getImplementationId( class_data * cd )
275 : SAL_THROW( (RuntimeException) )
276 : {
277 364 : if (! cd->m_createdId)
278 : {
279 53 : sal_uInt8 * id = (sal_uInt8 *)alloca( 16 );
280 53 : ::rtl_createUuid( (sal_uInt8 *)id, 0, sal_True );
281 :
282 53 : MutexGuard guard( getImplHelperInitMutex() );
283 53 : if (! cd->m_createdId)
284 : {
285 53 : memcpy( cd->m_id, id, 16 );
286 53 : cd->m_createdId = sal_True;
287 53 : }
288 : }
289 :
290 364 : sal_Sequence * seq = 0;
291 364 : ::rtl_byte_sequence_constructFromArray( &seq, cd->m_id, 16 );
292 364 : return Sequence< sal_Int8 >( seq, SAL_NO_ACQUIRE );
293 : }
294 : //==================================================================================================
295 0 : Sequence< Type > SAL_CALL ImplHelper_getTypes(
296 : class_data * cd )
297 : SAL_THROW( (RuntimeException) )
298 : {
299 0 : Sequence< Type > types( cd->m_nTypes );
300 0 : Type * pTypes = types.getArray();
301 0 : __fillTypes( pTypes, cd );
302 0 : return types;
303 : }
304 : //==================================================================================================
305 1 : Sequence< Type > SAL_CALL ImplInhHelper_getTypes(
306 : class_data * cd, Sequence< Type > const & rAddTypes )
307 : SAL_THROW( (RuntimeException) )
308 : {
309 1 : sal_Int32 nImplTypes = cd->m_nTypes;
310 1 : sal_Int32 nAddTypes = rAddTypes.getLength();
311 1 : Sequence< Type > types( nImplTypes + nAddTypes );
312 1 : Type * pTypes = types.getArray();
313 1 : __fillTypes( pTypes, cd );
314 : // append base types
315 1 : Type const * pAddTypes = rAddTypes.getConstArray();
316 5 : while (nAddTypes--)
317 : {
318 3 : pTypes[ nImplTypes + nAddTypes ] = pAddTypes[ nAddTypes ];
319 : }
320 1 : return types;
321 : }
322 :
323 : // WeakImplHelper
324 : //==================================================================================================
325 615551 : Any SAL_CALL WeakImplHelper_query(
326 : Type const & rType, class_data * cd, void * that, OWeakObject * pBase )
327 : SAL_THROW( (RuntimeException) )
328 : {
329 615551 : checkInterface( rType );
330 615551 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
331 :
332 : // shortcut XInterface to OWeakObject
333 615551 : if (! isXInterface( pTDR->pTypeName ))
334 : {
335 553839 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
336 553839 : if (p)
337 : {
338 384904 : return Any( &p, pTDR );
339 : }
340 : }
341 230647 : return pBase->OWeakObject::queryInterface( rType );
342 : }
343 : //==================================================================================================
344 452 : Sequence< Type > SAL_CALL WeakImplHelper_getTypes(
345 : class_data * cd )
346 : SAL_THROW( (RuntimeException) )
347 : {
348 452 : sal_Int32 nTypes = cd->m_nTypes;
349 452 : Sequence< Type > types( nTypes +1 );
350 452 : Type * pTypes = types.getArray();
351 452 : __fillTypes( pTypes, cd );
352 452 : pTypes[ nTypes ] = ::getCppuType( (Reference< XWeak > const *)0 );
353 452 : return types;
354 : }
355 :
356 : // WeakAggImplHelper
357 : //==================================================================================================
358 88213 : Any SAL_CALL WeakAggImplHelper_queryAgg(
359 : Type const & rType, class_data * cd, void * that, OWeakAggObject * pBase )
360 : SAL_THROW( (RuntimeException) )
361 : {
362 88213 : checkInterface( rType );
363 88213 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
364 :
365 : // shortcut XInterface to OWeakAggObject
366 88213 : if (! isXInterface( pTDR->pTypeName ))
367 : {
368 83697 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
369 83697 : if (p)
370 : {
371 56816 : return Any( &p, pTDR );
372 : }
373 : }
374 31397 : return pBase->OWeakAggObject::queryAggregation( rType );
375 : }
376 : //==================================================================================================
377 202 : Sequence< Type > SAL_CALL WeakAggImplHelper_getTypes(
378 : class_data * cd )
379 : SAL_THROW( (RuntimeException) )
380 : {
381 202 : sal_Int32 nTypes = cd->m_nTypes;
382 202 : Sequence< Type > types( nTypes +2 );
383 202 : Type * pTypes = types.getArray();
384 202 : __fillTypes( pTypes, cd );
385 202 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
386 202 : pTypes[ nTypes ] = ::getCppuType( (const Reference< XAggregation > *)0 );
387 202 : return types;
388 : }
389 :
390 : // WeakComponentImplHelper
391 : //==================================================================================================
392 347418 : Any SAL_CALL WeakComponentImplHelper_query(
393 : Type const & rType, class_data * cd, void * that, WeakComponentImplHelperBase * pBase )
394 : SAL_THROW( (RuntimeException) )
395 : {
396 347418 : checkInterface( rType );
397 347418 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
398 :
399 : // shortcut XInterface to WeakComponentImplHelperBase
400 347418 : if (! isXInterface( pTDR->pTypeName ))
401 : {
402 346953 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
403 346953 : if (p)
404 : {
405 330638 : return Any( &p, pTDR );
406 : }
407 : }
408 16780 : return pBase->WeakComponentImplHelperBase::queryInterface( rType );
409 : }
410 : //==================================================================================================
411 12 : Sequence< Type > SAL_CALL WeakComponentImplHelper_getTypes(
412 : class_data * cd )
413 : SAL_THROW( (RuntimeException) )
414 : {
415 12 : sal_Int32 nTypes = cd->m_nTypes;
416 12 : Sequence< Type > types( nTypes +2 );
417 12 : Type * pTypes = types.getArray();
418 12 : __fillTypes( pTypes, cd );
419 12 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
420 12 : pTypes[ nTypes ] = ::getCppuType( (Reference< lang::XComponent > const *)0 );
421 12 : return types;
422 : }
423 :
424 : // WeakAggComponentImplHelper
425 : //==================================================================================================
426 51 : Any SAL_CALL WeakAggComponentImplHelper_queryAgg(
427 : Type const & rType, class_data * cd, void * that, WeakAggComponentImplHelperBase * pBase )
428 : SAL_THROW( (RuntimeException) )
429 : {
430 51 : checkInterface( rType );
431 51 : typelib_TypeDescriptionReference * pTDR = rType.getTypeLibType();
432 :
433 : // shortcut XInterface to WeakAggComponentImplHelperBase
434 51 : if (! isXInterface( pTDR->pTypeName ))
435 : {
436 43 : void * p = __queryDeepNoXInterface( pTDR, cd, that );
437 43 : if (p)
438 : {
439 18 : return Any( &p, pTDR );
440 : }
441 : }
442 33 : return pBase->WeakAggComponentImplHelperBase::queryAggregation( rType );
443 : }
444 : //==================================================================================================
445 0 : Sequence< Type > SAL_CALL WeakAggComponentImplHelper_getTypes(
446 : class_data * cd )
447 : SAL_THROW( (RuntimeException) )
448 : {
449 0 : sal_Int32 nTypes = cd->m_nTypes;
450 0 : Sequence< Type > types( nTypes +3 );
451 0 : Type * pTypes = types.getArray();
452 0 : __fillTypes( pTypes, cd );
453 0 : pTypes[ nTypes++ ] = ::getCppuType( (Reference< XWeak > const *)0 );
454 0 : pTypes[ nTypes++ ] = ::getCppuType( (const Reference< XAggregation > *)0 );
455 0 : pTypes[ nTypes ] = ::getCppuType( (const Reference< lang::XComponent > *)0 );
456 0 : return types;
457 : }
458 :
459 : }
460 :
461 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|