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