xref: /trunk/main/testtools/source/performance/pseudo.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_testtools.hxx"
30 #include <osl/diagnose.h>
31 #include <osl/interlck.h>
32 #include <rtl/ustring.hxx>
33 #include <typelib/typedescription.h>
34 #include <uno/dispatcher.h>
35 #include <uno/environment.h>
36 #include <uno/mapping.h>
37 #include <uno/lbnames.h>
38 
39 using namespace rtl;
40 
41 
42 namespace pseudo_uno
43 {
44 
45 //==================================================================================================
46 struct pseudo_Mapping : public uno_Mapping
47 {
48     oslInterlockedCount     nRef;
49 
50     uno_ExtEnvironment *    pFrom;
51     uno_ExtEnvironment *    pTo;
52 
53     pseudo_Mapping( uno_ExtEnvironment * pFrom_, uno_ExtEnvironment * pTo_ );
54     ~pseudo_Mapping();
55 };
56 
57 //==== a uno pseudo proxy =============================================================================
58 struct pseudo_unoInterfaceProxy : public uno_Interface
59 {
60     oslInterlockedCount                 nRef;
61     pseudo_Mapping *                    pPseudoMapping;
62 
63     // mapping information
64     uno_Interface *                     pUnoI; // wrapped interface
65     typelib_InterfaceTypeDescription *  pTypeDescr;
66     OUString                            oid;
67 
68     // ctor
69     inline pseudo_unoInterfaceProxy( pseudo_Mapping * pPseudoMapping_,
70                                      uno_Interface * pUnoI_,
71                                      typelib_InterfaceTypeDescription * pTypeDescr_,
72                                      const OUString & rOId_ );
73 };
74 //--------------------------------------------------------------------------------------------------
75 static void SAL_CALL pseudo_unoInterfaceProxy_dispatch(
76     uno_Interface * pUnoI,
77     const typelib_TypeDescription * pMemberType,
78     void * pReturn,
79     void * pArgs[],
80     uno_Any ** ppException )
81 {
82     pseudo_unoInterfaceProxy * pThis = static_cast< pseudo_unoInterfaceProxy * >( pUnoI );
83     (*pThis->pUnoI->pDispatcher)( pThis->pUnoI, pMemberType, pReturn, pArgs, ppException );
84 }
85 
86 //--------------------------------------------------------------------------------------------------
87 static void SAL_CALL pseudo_unoInterfaceProxy_free( uno_ExtEnvironment * pEnv, void * pProxy )
88 {
89     pseudo_unoInterfaceProxy * pThis =
90         static_cast< pseudo_unoInterfaceProxy * >(
91             reinterpret_cast< uno_Interface * >( pProxy ) );
92     OSL_ASSERT( pEnv == pThis->pPseudoMapping->pTo );
93 
94     (*pThis->pPseudoMapping->pFrom->revokeInterface)( pThis->pPseudoMapping->pFrom, pThis->pUnoI );
95     (*pThis->pUnoI->release)( pThis->pUnoI );
96     typelib_typedescription_release( (typelib_TypeDescription *)pThis->pTypeDescr );
97     (*pThis->pPseudoMapping->release)( pThis->pPseudoMapping );
98 
99 #if OSL_DEBUG_LEVEL > 1
100     *(int *)pProxy = 0xdeadbabe;
101 #endif
102     delete pThis;
103 }
104 //--------------------------------------------------------------------------------------------------
105 static void SAL_CALL pseudo_unoInterfaceProxy_acquire( uno_Interface * pUnoI )
106 {
107     if (1 == osl_incrementInterlockedCount( &static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->nRef ))
108     {
109         // rebirth of proxy zombie
110         // register at uno env
111         void * pThis = static_cast< uno_Interface * >( pUnoI );
112         (*static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo->registerProxyInterface)(
113             static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo,
114             &pThis, pseudo_unoInterfaceProxy_free,
115             static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->oid.pData,
116             static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pTypeDescr );
117         OSL_ASSERT( pThis == static_cast< uno_Interface * >( pUnoI ) );
118     }
119 }
120 //--------------------------------------------------------------------------------------------------
121 static void SAL_CALL pseudo_unoInterfaceProxy_release( uno_Interface * pUnoI )
122 {
123     if (! osl_decrementInterlockedCount( & static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->nRef ))
124     {
125         // revoke from uno env on last release
126         (*static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo->revokeInterface)(
127             static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo, pUnoI );
128     }
129 }
130 //__________________________________________________________________________________________________
131 inline pseudo_unoInterfaceProxy::pseudo_unoInterfaceProxy(
132     pseudo_Mapping * pPseudoMapping_, uno_Interface * pUnoI_,
133     typelib_InterfaceTypeDescription * pTypeDescr_, const OUString & rOId_ )
134     : nRef( 1 )
135     , pPseudoMapping( pPseudoMapping_ )
136     , pUnoI( pUnoI_ )
137     , pTypeDescr( pTypeDescr_ )
138     , oid( rOId_ )
139 {
140     (*pPseudoMapping->acquire)( pPseudoMapping );
141     typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr );
142     (*pPseudoMapping->pFrom->registerInterface)(
143         pPseudoMapping->pFrom, reinterpret_cast< void ** >( &pUnoI ), oid.pData, pTypeDescr );
144     (*pUnoI->acquire)( pUnoI );
145 
146     // uno_Interface
147     uno_Interface::acquire = pseudo_unoInterfaceProxy_acquire;
148     uno_Interface::release = pseudo_unoInterfaceProxy_release;
149     uno_Interface::pDispatcher = pseudo_unoInterfaceProxy_dispatch;
150 }
151 
152 //--------------------------------------------------------------------------------------------------
153 static void SAL_CALL pseudo_Mapping_mapInterface(
154     uno_Mapping * pMapping, void ** ppOut,
155     void * pUnoI, typelib_InterfaceTypeDescription * pTypeDescr )
156 {
157     OSL_ASSERT( ppOut && pTypeDescr );
158     if (*ppOut)
159     {
160         (*reinterpret_cast< uno_Interface * >( *ppOut )->release)(
161             reinterpret_cast< uno_Interface * >( *ppOut ) );
162         *ppOut = 0;
163     }
164     if (pUnoI && pTypeDescr)
165     {
166         // get object id of uno interface to be wrapped
167         rtl_uString * pOId = 0;
168         (*static_cast< pseudo_Mapping * >( pMapping )->pFrom->getObjectIdentifier)(
169             static_cast< pseudo_Mapping * >( pMapping )->pFrom, &pOId, pUnoI );
170         OSL_ASSERT( pOId );
171 
172         if (pOId)
173         {
174             // try to get any known interface from target environment
175             (*static_cast< pseudo_Mapping * >( pMapping )->pTo->getRegisteredInterface)(
176                 static_cast< pseudo_Mapping * >( pMapping )->pTo, ppOut, pOId, pTypeDescr );
177             if (! *ppOut) // no existing interface, register new proxy interface
178             {
179                 // try to publish a new proxy (ref count initially 1)
180                 void * pProxy = new pseudo_unoInterfaceProxy(
181                     static_cast< pseudo_Mapping * >( pMapping ),
182                     reinterpret_cast< uno_Interface * >( pUnoI ), pTypeDescr, pOId );
183 
184                 // proxy may be exchanged during registration
185                 (*static_cast< pseudo_Mapping * >( pMapping )->pTo->registerProxyInterface)(
186                     static_cast< pseudo_Mapping * >( pMapping )->pTo,
187                     &pProxy, pseudo_unoInterfaceProxy_free, pOId, pTypeDescr );
188 
189                 *ppOut = pProxy;
190             }
191             rtl_uString_release( pOId );
192         }
193     }
194 }
195 //--------------------------------------------------------------------------------------------------
196 static void SAL_CALL pseudo_Mapping_free( uno_Mapping * pMapping )
197 {
198     delete static_cast< pseudo_Mapping * >( pMapping );
199 }
200 //--------------------------------------------------------------------------------------------------
201 static void SAL_CALL pseudo_Mapping_acquire( uno_Mapping * pMapping )
202 {
203     if (1 == osl_incrementInterlockedCount( & static_cast< pseudo_Mapping * >( pMapping )->nRef ))
204     {
205         OUString aMappingPurpose( RTL_CONSTASCII_USTRINGPARAM("pseudo") );
206         uno_registerMapping( &pMapping,
207                              pseudo_Mapping_free,
208                              (uno_Environment *)((pseudo_Mapping *)pMapping)->pFrom,
209                              (uno_Environment *)((pseudo_Mapping *)pMapping)->pTo,
210                              aMappingPurpose.pData );
211     }
212 }
213 //--------------------------------------------------------------------------------------------------
214 static void SAL_CALL pseudo_Mapping_release( uno_Mapping * pMapping )
215 {
216     if (! osl_decrementInterlockedCount( & static_cast< pseudo_Mapping * >( pMapping )->nRef ))
217     {
218         uno_revokeMapping( pMapping );
219     }
220 }
221 
222 //__________________________________________________________________________________________________
223 pseudo_Mapping::pseudo_Mapping( uno_ExtEnvironment * pFrom_, uno_ExtEnvironment * pTo_ )
224     : nRef( 1 )
225     , pFrom( pFrom_ )
226     , pTo( pTo_ )
227 {
228     (*((uno_Environment *)pFrom)->acquire)( (uno_Environment *)pFrom );
229     (*((uno_Environment *)pTo)->acquire)( (uno_Environment *)pTo );
230     //
231     uno_Mapping::acquire = pseudo_Mapping_acquire;
232     uno_Mapping::release = pseudo_Mapping_release;
233     uno_Mapping::mapInterface = pseudo_Mapping_mapInterface;
234 }
235 //__________________________________________________________________________________________________
236 pseudo_Mapping::~pseudo_Mapping()
237 {
238     (*((uno_Environment *)pTo)->release)( (uno_Environment *)pTo );
239     (*((uno_Environment *)pFrom)->release)( (uno_Environment *)pFrom );
240 }
241 
242 }
243 
244 //##################################################################################################
245 extern "C" void SAL_CALL uno_initEnvironment( uno_Environment * pUnoEnv )
246 {
247     OSL_ENSURE( sal_False, "### no impl: unexpected call!" );
248 }
249 //##################################################################################################
250 extern "C" void SAL_CALL uno_ext_getMapping(
251     uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo )
252 {
253     OSL_ASSERT( ppMapping && pFrom && pTo );
254     if (ppMapping && pFrom && pTo && pFrom->pExtEnv && pTo->pExtEnv)
255     {
256         uno_Mapping * pMapping = 0;
257 
258         if (0 == rtl_ustr_ascii_compare( pFrom->pTypeName->buffer, UNO_LB_UNO ) &&
259             0 == rtl_ustr_ascii_compare( pTo->pTypeName->buffer, UNO_LB_UNO ))
260         {
261             OUString aMappingPurpose( RTL_CONSTASCII_USTRINGPARAM("pseudo") );
262             // ref count is initially 1
263             pMapping = new pseudo_uno::pseudo_Mapping( pFrom->pExtEnv, pTo->pExtEnv );
264             uno_registerMapping( &pMapping, pseudo_uno::pseudo_Mapping_free,
265                                  (uno_Environment *)pFrom->pExtEnv,
266                                  (uno_Environment *)pTo->pExtEnv,
267                                  aMappingPurpose.pData );
268         }
269 
270         if (*ppMapping)
271             (*(*ppMapping)->release)( *ppMapping );
272         *ppMapping = pMapping;
273     }
274 }
275