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_cppu.hxx"
26
27 #include "cppu/helper/purpenv/Mapping.hxx"
28
29 #include "Proxy.hxx"
30
31 #include "osl/interlck.h"
32 #include "uno/environment.hxx"
33 #include "uno/dispatcher.h"
34 #include "typelib/typedescription.h"
35
36
37 #ifdef debug
38 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping
39 #endif
40
41 #ifdef LOG_LIFECYCLE_cppu_helper_purpenv_Mapping
42 # include <iostream>
43 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x) x
44
45 #else
46 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x)
47
48 #endif
49
50
51 using namespace com::sun::star;
52
53
54 class Mapping : public uno_Mapping
55 {
56 uno::Environment m_from;
57 uno::Environment m_to;
58
59 oslInterlockedCount m_nCount;
60
61 cppu::helper::purpenv::ProbeFun * m_probeFun;
62 void * m_pContext;
63
64 public:
65 explicit Mapping(uno_Environment * pFrom,
66 uno_Environment * pTo,
67 cppu::helper::purpenv::ProbeFun * probeFun,
68 void * pProbeContext);
69 virtual ~Mapping(void);
70
71 void mapInterface(
72 uno_Interface ** ppOut,
73 uno_Interface * pUnoI,
74 typelib_InterfaceTypeDescription * pTypeDescr);
75
76 void acquire(void);
77 void release(void);
78 };
79
s_mapInterface(uno_Mapping * puno_Mapping,uno_Interface ** ppOut,uno_Interface * pUnoI,typelib_InterfaceTypeDescription * pTypeDescr)80 static void SAL_CALL s_mapInterface(
81 uno_Mapping * puno_Mapping,
82 uno_Interface ** ppOut,
83 uno_Interface * pUnoI,
84 typelib_InterfaceTypeDescription * pTypeDescr )
85 SAL_THROW_EXTERN_C()
86 {
87 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
88 pMapping->mapInterface(ppOut, pUnoI, pTypeDescr);
89 }
90
91 extern "C" {
s_acquire(uno_Mapping * puno_Mapping)92 static void SAL_CALL s_acquire(uno_Mapping * puno_Mapping)
93 SAL_THROW_EXTERN_C()
94 {
95 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
96 pMapping->acquire();
97 }
98
s_release(uno_Mapping * puno_Mapping)99 static void SAL_CALL s_release(uno_Mapping * puno_Mapping)
100 SAL_THROW_EXTERN_C()
101 {
102 Mapping * pMapping = static_cast<Mapping * >(puno_Mapping);
103 pMapping->release();
104 }
105
106
s_getIdentifier_v(va_list * pParam)107 static void s_getIdentifier_v(va_list * pParam)
108 {
109 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
110 rtl_uString ** ppOid = va_arg(*pParam, rtl_uString **);
111 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
112
113 pEnv->getObjectIdentifier(pEnv, ppOid, pUnoI);
114 }
115
s_free(uno_Mapping * puno_Mapping)116 static void SAL_CALL s_free(uno_Mapping * puno_Mapping)
117 SAL_THROW_EXTERN_C()
118 {
119 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
120 delete pMapping;
121 }
122 }
123
Mapping(uno_Environment * pFrom,uno_Environment * pTo,cppu::helper::purpenv::ProbeFun * probeFun,void * pProbeContext)124 Mapping::Mapping(uno_Environment * pFrom,
125 uno_Environment * pTo,
126 cppu::helper::purpenv::ProbeFun * probeFun,
127 void * pProbeContext
128 ) SAL_THROW( () )
129 : m_from (pFrom),
130 m_to (pTo),
131 m_nCount (1),
132 m_probeFun(probeFun),
133 m_pContext(pProbeContext)
134 {
135 LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo) SAL_THROW( () )", this));
136
137 uno_Mapping::acquire = s_acquire;
138 uno_Mapping::release = s_release;
139 uno_Mapping::mapInterface = (uno_MapInterfaceFunc)s_mapInterface;
140 }
141
~Mapping(void)142 Mapping::~Mapping(void)
143 {
144 LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::~Mapping(void)", this));
145 }
146
147
mapInterface(uno_Interface ** ppOut,uno_Interface * pUnoI,typelib_InterfaceTypeDescription * pTypeDescr)148 void Mapping::mapInterface(
149 uno_Interface ** ppOut,
150 uno_Interface * pUnoI,
151 typelib_InterfaceTypeDescription * pTypeDescr)
152 {
153 OSL_ASSERT(ppOut && pTypeDescr);
154 if (*ppOut)
155 {
156 (*ppOut)->release(*ppOut);
157 *ppOut = 0;
158 }
159
160 if (!pUnoI)
161 return;
162
163 // get object id of uno interface to be wrapped
164 // need to enter environment because of potential "queryInterface" call
165 rtl_uString * pOId = 0;
166 uno_Environment_invoke(m_from.get(), s_getIdentifier_v, m_from.get(), &pOId, pUnoI);
167 OSL_ASSERT(pOId);
168
169 // try to get any known interface from target environment
170 m_to.get()->pExtEnv->getRegisteredInterface(m_to.get()->pExtEnv, (void **)ppOut, pOId, pTypeDescr);
171
172 if (!*ppOut) // not yet there, register new proxy interface
173 {
174 // try to publish a new proxy (ref count initially 1)
175 uno_Interface * pProxy = new Proxy(this,
176 m_from.get(),
177 m_to.get(),
178 pUnoI,
179 pTypeDescr,
180 pOId,
181 m_probeFun,
182 m_pContext);
183
184 // proxy may be exchanged during registration
185 m_to.get()->pExtEnv->registerProxyInterface(m_to.get()->pExtEnv,
186 (void **)&pProxy,
187 Proxy_free,
188 pOId,
189 pTypeDescr);
190
191 *ppOut = pProxy;
192 }
193
194 rtl_uString_release(pOId);
195 }
196
197
acquire()198 void Mapping::acquire() SAL_THROW(())
199 {
200 if (osl_incrementInterlockedCount(&m_nCount) == 1)
201 {
202 uno_Mapping * pMapping = this;
203
204 ::uno_registerMapping(&pMapping, s_free, m_from.get(), m_to.get(), NULL);
205 }
206 }
207
release()208 void Mapping::release() SAL_THROW(())
209 {
210 if (osl_decrementInterlockedCount(&m_nCount) == 0)
211 ::uno_revokeMapping(this);
212 }
213
214
215 namespace cppu { namespace helper { namespace purpenv {
216
createMapping(uno_Mapping ** ppMapping,uno_Environment * pFrom,uno_Environment * pTo,ProbeFun * probeFun,void * pContext)217 void createMapping(uno_Mapping ** ppMapping,
218 uno_Environment * pFrom,
219 uno_Environment * pTo,
220 ProbeFun * probeFun,
221 void * pContext
222 )
223 {
224 *ppMapping = new Mapping(pFrom, pTo, probeFun, pContext);
225
226 ::uno_registerMapping(ppMapping, s_free, pFrom, pTo, NULL);
227 }
228
229 }}}
230