1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26 
27 #include "bridges/cpp_uno/shared/bridge.hxx"
28 
29 #include "component.hxx"
30 
31 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
32 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
33 
34 #include "com/sun/star/uno/XInterface.hpp"
35 #include "osl/diagnose.h"
36 #include "osl/interlck.h"
37 #include "rtl/ustring.h"
38 #include "sal/types.h"
39 #include "typelib/typedescription.h"
40 #include "uno/dispatcher.h"
41 #include "uno/environment.h"
42 #include "uno/mapping.h"
43 
44 namespace bridges { namespace cpp_uno { namespace shared {
45 
freeMapping(uno_Mapping * pMapping)46 void freeMapping(uno_Mapping * pMapping)
47 {
48     delete static_cast< Bridge::Mapping * >( pMapping )->pBridge;
49 }
50 
acquireMapping(uno_Mapping * pMapping)51 void acquireMapping(uno_Mapping * pMapping)
52 {
53     static_cast< Bridge::Mapping * >( pMapping )->pBridge->acquire();
54 }
55 
releaseMapping(uno_Mapping * pMapping)56 void releaseMapping(uno_Mapping * pMapping)
57 {
58     static_cast< Bridge::Mapping * >( pMapping )->pBridge->release();
59 }
60 
cpp2unoMapping(uno_Mapping * pMapping,void ** ppUnoI,void * pCppI,typelib_InterfaceTypeDescription * pTypeDescr)61 void cpp2unoMapping(
62     uno_Mapping * pMapping, void ** ppUnoI, void * pCppI,
63     typelib_InterfaceTypeDescription * pTypeDescr)
64 {
65     OSL_ENSURE( ppUnoI && pTypeDescr, "### null ptr!" );
66     if (*ppUnoI)
67     {
68         (*reinterpret_cast< uno_Interface * >( *ppUnoI )->release)(
69             reinterpret_cast< uno_Interface * >( *ppUnoI ) );
70         *ppUnoI = 0;
71     }
72     if (pCppI)
73     {
74         Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge;
75 
76         // get object id of interface to be wrapped
77         rtl_uString * pOId = 0;
78         (*pBridge->pCppEnv->getObjectIdentifier)(
79             pBridge->pCppEnv, &pOId, pCppI );
80         OSL_ASSERT( pOId );
81 
82         // try to get any known interface from target environment
83         (*pBridge->pUnoEnv->getRegisteredInterface)(
84             pBridge->pUnoEnv, ppUnoI, pOId, pTypeDescr );
85 
86         if (! *ppUnoI) // no existing interface, register new proxy interface
87         {
88             // try to publish a new proxy (refcount initially 1)
89             uno_Interface * pSurrogate
90                 = bridges::cpp_uno::shared::UnoInterfaceProxy::create(
91                     pBridge,
92                     static_cast< ::com::sun::star::uno::XInterface * >( pCppI ),
93                     pTypeDescr, pOId );
94 
95             // proxy may be exchanged during registration
96             (*pBridge->pUnoEnv->registerProxyInterface)(
97                 pBridge->pUnoEnv, reinterpret_cast< void ** >( &pSurrogate ),
98                 freeUnoInterfaceProxy, pOId,
99                 pTypeDescr );
100 
101             *ppUnoI = pSurrogate;
102         }
103         ::rtl_uString_release( pOId );
104     }
105 }
106 
uno2cppMapping(uno_Mapping * pMapping,void ** ppCppI,void * pUnoI,typelib_InterfaceTypeDescription * pTypeDescr)107 void uno2cppMapping(
108     uno_Mapping * pMapping, void ** ppCppI, void * pUnoI,
109     typelib_InterfaceTypeDescription * pTypeDescr)
110 {
111     OSL_ASSERT( ppCppI && pTypeDescr );
112     if (*ppCppI)
113     {
114         static_cast< ::com::sun::star::uno::XInterface * >( *ppCppI )->
115             release();
116         *ppCppI = 0;
117     }
118     if (pUnoI)
119     {
120         Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge;
121 
122         // get object id of uno interface to be wrapped
123         rtl_uString * pOId = 0;
124         (*pBridge->pUnoEnv->getObjectIdentifier)(
125             pBridge->pUnoEnv, &pOId, pUnoI );
126         OSL_ASSERT( pOId );
127 
128         // try to get any known interface from target environment
129         (*pBridge->pCppEnv->getRegisteredInterface)(
130             pBridge->pCppEnv, ppCppI, pOId, pTypeDescr );
131 
132         if (! *ppCppI) // no existing interface, register new proxy interface
133         {
134             // try to publish a new proxy (ref count initially 1)
135             com::sun::star::uno::XInterface * pProxy
136                 = bridges::cpp_uno::shared::CppInterfaceProxy::create(
137                     pBridge, static_cast< uno_Interface * >( pUnoI ),
138                     pTypeDescr, pOId );
139 
140             // proxy may be exchanged during registration
141             (*pBridge->pCppEnv->registerProxyInterface)(
142                 pBridge->pCppEnv, reinterpret_cast< void ** >( &pProxy ),
143                 freeCppInterfaceProxy, pOId,
144                 pTypeDescr );
145 
146             *ppCppI = pProxy;
147         }
148         ::rtl_uString_release( pOId );
149     }
150 }
151 
createMapping(uno_ExtEnvironment * pCppEnv,uno_ExtEnvironment * pUnoEnv,bool bExportCpp2Uno)152 uno_Mapping * Bridge::createMapping(
153     uno_ExtEnvironment * pCppEnv, uno_ExtEnvironment * pUnoEnv,
154     bool bExportCpp2Uno) SAL_THROW(())
155 {
156     Bridge * bridge = new Bridge(pCppEnv, pUnoEnv, bExportCpp2Uno);
157     return bExportCpp2Uno ? &bridge->aCpp2Uno : &bridge->aUno2Cpp;
158 }
159 
acquire()160 void Bridge::acquire() SAL_THROW(())
161 {
162     if (1 == osl_incrementInterlockedCount( &nRef ))
163     {
164         if (bExportCpp2Uno)
165         {
166             uno_Mapping * pMapping = &aCpp2Uno;
167             ::uno_registerMapping(
168                 &pMapping, freeMapping, (uno_Environment *)pCppEnv,
169                 (uno_Environment *)pUnoEnv, 0 );
170         }
171         else
172         {
173             uno_Mapping * pMapping = &aUno2Cpp;
174             ::uno_registerMapping(
175                 &pMapping, freeMapping, (uno_Environment *)pUnoEnv,
176                 (uno_Environment *)pCppEnv, 0 );
177         }
178     }
179 }
180 
release()181 void Bridge::release() SAL_THROW(())
182 {
183     if (! osl_decrementInterlockedCount( &nRef ))
184     {
185         ::uno_revokeMapping( bExportCpp2Uno ? &aCpp2Uno : &aUno2Cpp );
186     }
187 }
188 
Bridge(uno_ExtEnvironment * pCppEnv_,uno_ExtEnvironment * pUnoEnv_,bool bExportCpp2Uno_)189 Bridge::Bridge(
190     uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_,
191     bool bExportCpp2Uno_) SAL_THROW(())
192     : nRef( 1 )
193     , pCppEnv( pCppEnv_ )
194     , pUnoEnv( pUnoEnv_ )
195     , bExportCpp2Uno( bExportCpp2Uno_ )
196 {
197     bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire(
198         &bridges::cpp_uno::shared::g_moduleCount.modCnt );
199 
200     aCpp2Uno.pBridge = this;
201     aCpp2Uno.acquire = acquireMapping;
202     aCpp2Uno.release = releaseMapping;
203     aCpp2Uno.mapInterface = cpp2unoMapping;
204 
205     aUno2Cpp.pBridge = this;
206     aUno2Cpp.acquire = acquireMapping;
207     aUno2Cpp.release = releaseMapping;
208     aUno2Cpp.mapInterface = uno2cppMapping;
209 
210     (*((uno_Environment *)pCppEnv)->acquire)( (uno_Environment *)pCppEnv );
211     (*((uno_Environment *)pUnoEnv)->acquire)( (uno_Environment *)pUnoEnv );
212 }
213 
~Bridge()214 Bridge::~Bridge() SAL_THROW(())
215 {
216     (*((uno_Environment *)pUnoEnv)->release)( (uno_Environment *)pUnoEnv );
217     (*((uno_Environment *)pCppEnv)->release)( (uno_Environment *)pCppEnv );
218     bridges::cpp_uno::shared::g_moduleCount.modCnt.release(
219         &bridges::cpp_uno::shared::g_moduleCount.modCnt );
220 }
221 
222 } } }
223