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