1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21 #include <cppu/helper/purpenv/Mapping.hxx>
22
23 #include "Proxy.hxx"
24
25 #include <osl/interlck.h>
26 #include <sal/log.hxx>
27 #include <uno/environment.hxx>
28 #include <uno/dispatcher.h>
29
30 using namespace com::sun::star;
31
32 class Mapping : public uno_Mapping
33 {
34 uno::Environment m_from;
35 uno::Environment m_to;
36
37 oslInterlockedCount m_nCount;
38
39 cppu::helper::purpenv::ProbeFun * m_probeFun;
40 void * m_pContext;
41
42 public:
43 explicit Mapping(uno_Environment * pFrom,
44 uno_Environment * pTo,
45 cppu::helper::purpenv::ProbeFun * probeFun,
46 void * pProbeContext);
47 virtual ~Mapping();
48
49 void mapInterface(
50 uno_Interface ** ppOut,
51 uno_Interface * pUnoI,
52 typelib_InterfaceTypeDescription * pTypeDescr);
53
54 void acquire();
55 void release();
56 };
57
s_mapInterface(uno_Mapping * puno_Mapping,void ** ppOut,void * pUnoI,typelib_InterfaceTypeDescription * pTypeDescr)58 static void s_mapInterface(
59 uno_Mapping * puno_Mapping,
60 void ** ppOut,
61 void * pUnoI,
62 typelib_InterfaceTypeDescription * pTypeDescr )
63 SAL_THROW_EXTERN_C()
64 {
65 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
66 pMapping->mapInterface(
67 reinterpret_cast<uno_Interface **>(ppOut),
68 static_cast<uno_Interface *>(pUnoI), pTypeDescr);
69 }
70
71 extern "C" {
s_acquire(uno_Mapping * puno_Mapping)72 static void s_acquire(uno_Mapping * puno_Mapping)
73 SAL_THROW_EXTERN_C()
74 {
75 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
76 pMapping->acquire();
77 }
78
s_release(uno_Mapping * puno_Mapping)79 static void s_release(uno_Mapping * puno_Mapping)
80 SAL_THROW_EXTERN_C()
81 {
82 Mapping * pMapping = static_cast<Mapping * >(puno_Mapping);
83 pMapping->release();
84 }
85
86
s_getIdentifier_v(va_list * pParam)87 static void s_getIdentifier_v(va_list * pParam)
88 {
89 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
90 rtl_uString ** ppOid = va_arg(*pParam, rtl_uString **);
91 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *);
92
93 pEnv->getObjectIdentifier(pEnv, ppOid, pUnoI);
94 }
95
s_free(uno_Mapping * puno_Mapping)96 static void s_free(uno_Mapping * puno_Mapping)
97 SAL_THROW_EXTERN_C()
98 {
99 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping);
100 delete pMapping;
101 }
102 }
103
Mapping(uno_Environment * pFrom,uno_Environment * pTo,cppu::helper::purpenv::ProbeFun * probeFun,void * pProbeContext)104 Mapping::Mapping(uno_Environment * pFrom,
105 uno_Environment * pTo,
106 cppu::helper::purpenv::ProbeFun * probeFun,
107 void * pProbeContext
108 )
109 : m_from (pFrom),
110 m_to (pTo),
111 m_nCount (1),
112 m_probeFun(probeFun),
113 m_pContext(pProbeContext)
114 {
115 SAL_INFO("cppu.purpenv", "LIFE: Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo -> " << this);
116
117 uno_Mapping::acquire = s_acquire;
118 uno_Mapping::release = s_release;
119 uno_Mapping::mapInterface = s_mapInterface;
120 }
121
~Mapping()122 Mapping::~Mapping()
123 {
124 SAL_INFO("cppu.purpenv", "LIFE: Mapping:~Mapping() -> " << this);
125 }
126
127
mapInterface(uno_Interface ** ppOut,uno_Interface * pUnoI,typelib_InterfaceTypeDescription * pTypeDescr)128 void Mapping::mapInterface(
129 uno_Interface ** ppOut,
130 uno_Interface * pUnoI,
131 typelib_InterfaceTypeDescription * pTypeDescr)
132 {
133 OSL_ASSERT(ppOut && pTypeDescr);
134 if (*ppOut)
135 {
136 (*ppOut)->release(*ppOut);
137 *ppOut = nullptr;
138 }
139
140 if (!pUnoI)
141 return;
142
143 // get object id of uno interface to be wrapped
144 // need to enter environment because of potential "queryInterface" call
145 rtl_uString * pOId = nullptr;
146 uno_Environment_invoke(m_from.get(), s_getIdentifier_v, m_from.get(), &pOId, pUnoI);
147 OSL_ASSERT(pOId);
148
149 // try to get any known interface from target environment
150 m_to.get()->pExtEnv->getRegisteredInterface(m_to.get()->pExtEnv, reinterpret_cast<void **>(ppOut), pOId, pTypeDescr);
151
152 if (!*ppOut) // not yet there, register new proxy interface
153 {
154 // try to publish a new proxy (ref count initially 1)
155 uno_Interface * pProxy = new Proxy(this,
156 m_from.get(),
157 m_to.get(),
158 pUnoI,
159 pTypeDescr,
160 pOId,
161 m_probeFun,
162 m_pContext);
163
164 // proxy may be exchanged during registration
165 m_to.get()->pExtEnv->registerProxyInterface(m_to.get()->pExtEnv,
166 reinterpret_cast<void **>(&pProxy),
167 Proxy_free,
168 pOId,
169 pTypeDescr);
170
171 *ppOut = pProxy;
172 }
173
174 rtl_uString_release(pOId);
175 }
176
177
acquire()178 void Mapping::acquire()
179 {
180 if (osl_atomic_increment(&m_nCount) == 1)
181 {
182 uno_Mapping * pMapping = this;
183
184 ::uno_registerMapping(&pMapping, s_free, m_from.get(), m_to.get(), nullptr);
185 }
186 }
187
release()188 void Mapping::release()
189 {
190 if (osl_atomic_decrement(&m_nCount) == 0)
191 ::uno_revokeMapping(this);
192 }
193
194
195 namespace cppu { namespace helper { namespace purpenv {
196
createMapping(uno_Mapping ** ppMapping,uno_Environment * pFrom,uno_Environment * pTo,ProbeFun * probeFun,void * pContext)197 void createMapping(uno_Mapping ** ppMapping,
198 uno_Environment * pFrom,
199 uno_Environment * pTo,
200 ProbeFun * probeFun,
201 void * pContext
202 )
203 {
204 *ppMapping = new Mapping(pFrom, pTo, probeFun, pContext);
205
206 ::uno_registerMapping(ppMapping, s_free, pFrom, pTo, nullptr);
207 }
208
209 }}}
210
211 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
212