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_bridges.hxx"
30 
31 #include "bridges/cpp_uno/shared/bridge.hxx"
32 
33 #include "component.hxx"
34 
35 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
36 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
37 
38 #include "com/sun/star/uno/XInterface.hpp"
39 #include "osl/diagnose.h"
40 #include "osl/interlck.h"
41 #include "rtl/ustring.h"
42 #include "sal/types.h"
43 #include "typelib/typedescription.h"
44 #include "uno/dispatcher.h"
45 #include "uno/environment.h"
46 #include "uno/mapping.h"
47 
48 namespace bridges { namespace cpp_uno { namespace shared {
49 
50 void freeMapping(uno_Mapping * pMapping)
51 {
52     delete static_cast< Bridge::Mapping * >( pMapping )->pBridge;
53 }
54 
55 void acquireMapping(uno_Mapping * pMapping)
56 {
57     static_cast< Bridge::Mapping * >( pMapping )->pBridge->acquire();
58 }
59 
60 void releaseMapping(uno_Mapping * pMapping)
61 {
62     static_cast< Bridge::Mapping * >( pMapping )->pBridge->release();
63 }
64 
65 void cpp2unoMapping(
66     uno_Mapping * pMapping, void ** ppUnoI, void * pCppI,
67     typelib_InterfaceTypeDescription * pTypeDescr)
68 {
69     OSL_ENSURE( ppUnoI && pTypeDescr, "### null ptr!" );
70     if (*ppUnoI)
71     {
72         (*reinterpret_cast< uno_Interface * >( *ppUnoI )->release)(
73             reinterpret_cast< uno_Interface * >( *ppUnoI ) );
74         *ppUnoI = 0;
75     }
76     if (pCppI)
77     {
78         Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge;
79 
80         // get object id of interface to be wrapped
81         rtl_uString * pOId = 0;
82         (*pBridge->pCppEnv->getObjectIdentifier)(
83             pBridge->pCppEnv, &pOId, pCppI );
84         OSL_ASSERT( pOId );
85 
86         // try to get any known interface from target environment
87         (*pBridge->pUnoEnv->getRegisteredInterface)(
88             pBridge->pUnoEnv, ppUnoI, pOId, pTypeDescr );
89 
90         if (! *ppUnoI) // no existing interface, register new proxy interface
91         {
92             // try to publish a new proxy (refcount initially 1)
93             uno_Interface * pSurrogate
94                 = bridges::cpp_uno::shared::UnoInterfaceProxy::create(
95                     pBridge,
96                     static_cast< ::com::sun::star::uno::XInterface * >( pCppI ),
97                     pTypeDescr, pOId );
98 
99             // proxy may be exchanged during registration
100             (*pBridge->pUnoEnv->registerProxyInterface)(
101                 pBridge->pUnoEnv, reinterpret_cast< void ** >( &pSurrogate ),
102                 freeUnoInterfaceProxy, pOId,
103                 pTypeDescr );
104 
105             *ppUnoI = pSurrogate;
106         }
107         ::rtl_uString_release( pOId );
108     }
109 }
110 
111 void uno2cppMapping(
112     uno_Mapping * pMapping, void ** ppCppI, void * pUnoI,
113     typelib_InterfaceTypeDescription * pTypeDescr)
114 {
115     OSL_ASSERT( ppCppI && pTypeDescr );
116     if (*ppCppI)
117     {
118         static_cast< ::com::sun::star::uno::XInterface * >( *ppCppI )->
119             release();
120         *ppCppI = 0;
121     }
122     if (pUnoI)
123     {
124         Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge;
125 
126         // get object id of uno interface to be wrapped
127         rtl_uString * pOId = 0;
128         (*pBridge->pUnoEnv->getObjectIdentifier)(
129             pBridge->pUnoEnv, &pOId, pUnoI );
130         OSL_ASSERT( pOId );
131 
132         // try to get any known interface from target environment
133         (*pBridge->pCppEnv->getRegisteredInterface)(
134             pBridge->pCppEnv, ppCppI, pOId, pTypeDescr );
135 
136         if (! *ppCppI) // no existing interface, register new proxy interface
137         {
138             // try to publish a new proxy (ref count initially 1)
139             com::sun::star::uno::XInterface * pProxy
140                 = bridges::cpp_uno::shared::CppInterfaceProxy::create(
141                     pBridge, static_cast< uno_Interface * >( pUnoI ),
142                     pTypeDescr, pOId );
143 
144             // proxy may be exchanged during registration
145             (*pBridge->pCppEnv->registerProxyInterface)(
146                 pBridge->pCppEnv, reinterpret_cast< void ** >( &pProxy ),
147                 freeCppInterfaceProxy, pOId,
148                 pTypeDescr );
149 
150             *ppCppI = pProxy;
151         }
152         ::rtl_uString_release( pOId );
153     }
154 }
155 
156 uno_Mapping * Bridge::createMapping(
157     uno_ExtEnvironment * pCppEnv, uno_ExtEnvironment * pUnoEnv,
158     bool bExportCpp2Uno) SAL_THROW(())
159 {
160     Bridge * bridge = new Bridge(pCppEnv, pUnoEnv, bExportCpp2Uno);
161     return bExportCpp2Uno ? &bridge->aCpp2Uno : &bridge->aUno2Cpp;
162 }
163 
164 void Bridge::acquire() SAL_THROW(())
165 {
166     if (1 == osl_incrementInterlockedCount( &nRef ))
167     {
168         if (bExportCpp2Uno)
169         {
170             uno_Mapping * pMapping = &aCpp2Uno;
171             ::uno_registerMapping(
172                 &pMapping, freeMapping, (uno_Environment *)pCppEnv,
173                 (uno_Environment *)pUnoEnv, 0 );
174         }
175         else
176         {
177             uno_Mapping * pMapping = &aUno2Cpp;
178             ::uno_registerMapping(
179                 &pMapping, freeMapping, (uno_Environment *)pUnoEnv,
180                 (uno_Environment *)pCppEnv, 0 );
181         }
182     }
183 }
184 
185 void Bridge::release() SAL_THROW(())
186 {
187     if (! osl_decrementInterlockedCount( &nRef ))
188     {
189         ::uno_revokeMapping( bExportCpp2Uno ? &aCpp2Uno : &aUno2Cpp );
190     }
191 }
192 
193 Bridge::Bridge(
194     uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_,
195     bool bExportCpp2Uno_) SAL_THROW(())
196     : nRef( 1 )
197     , pCppEnv( pCppEnv_ )
198     , pUnoEnv( pUnoEnv_ )
199     , bExportCpp2Uno( bExportCpp2Uno_ )
200 {
201     bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire(
202         &bridges::cpp_uno::shared::g_moduleCount.modCnt );
203 
204     aCpp2Uno.pBridge = this;
205     aCpp2Uno.acquire = acquireMapping;
206     aCpp2Uno.release = releaseMapping;
207     aCpp2Uno.mapInterface = cpp2unoMapping;
208 
209     aUno2Cpp.pBridge = this;
210     aUno2Cpp.acquire = acquireMapping;
211     aUno2Cpp.release = releaseMapping;
212     aUno2Cpp.mapInterface = uno2cppMapping;
213 
214     (*((uno_Environment *)pCppEnv)->acquire)( (uno_Environment *)pCppEnv );
215     (*((uno_Environment *)pUnoEnv)->acquire)( (uno_Environment *)pUnoEnv );
216 }
217 
218 Bridge::~Bridge() SAL_THROW(())
219 {
220     (*((uno_Environment *)pUnoEnv)->release)( (uno_Environment *)pUnoEnv );
221     (*((uno_Environment *)pCppEnv)->release)( (uno_Environment *)pCppEnv );
222     bridges::cpp_uno::shared::g_moduleCount.modCnt.release(
223         &bridges::cpp_uno::shared::g_moduleCount.modCnt );
224 }
225 
226 } } }
227