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 #include "sal/config.h"
25
26 #include <exception>
27 #include <vector>
28
29 #include "cppuhelper/exc_hlp.hxx"
30 #include "osl/diagnose.h"
31 #include "rtl/ref.hxx"
32 #include "rtl/ustring.hxx"
33 #include "sal/types.h"
34 #include "typelib/typedescription.h"
35 #include "typelib/typedescription.hxx"
36 #include "uno/any2.h"
37 #include "uno/dispatcher.h"
38 #include "uno/dispatcher.hxx"
39
40 #include "binaryany.hxx"
41 #include "bridge.hxx"
42 #include "proxy.hxx"
43
44 namespace binaryurp {
45
46 namespace {
47
48 namespace css = com::sun::star;
49
proxy_acquireInterface(uno_Interface * pInterface)50 extern "C" void SAL_CALL proxy_acquireInterface(uno_Interface * pInterface) {
51 OSL_ASSERT(pInterface != 0);
52 static_cast< Proxy * >(pInterface)->do_acquire();
53 }
54
proxy_releaseInterface(uno_Interface * pInterface)55 extern "C" void SAL_CALL proxy_releaseInterface(uno_Interface * pInterface) {
56 OSL_ASSERT(pInterface != 0);
57 static_cast< Proxy * >(pInterface)->do_release();
58 }
59
proxy_dispatchInterface(uno_Interface * pUnoI,typelib_TypeDescription const * pMemberType,void * pReturn,void ** pArgs,uno_Any ** ppException)60 extern "C" void SAL_CALL proxy_dispatchInterface(
61 uno_Interface * pUnoI, typelib_TypeDescription const * pMemberType,
62 void * pReturn, void ** pArgs, uno_Any ** ppException)
63 {
64 OSL_ASSERT(pUnoI != 0);
65 static_cast< Proxy * >(pUnoI)->do_dispatch(
66 pMemberType, pReturn, pArgs, ppException);
67 }
68
69 }
70
Proxy(rtl::Reference<Bridge> const & bridge,rtl::OUString const & oid,css::uno::TypeDescription const & type)71 Proxy::Proxy(
72 rtl::Reference< Bridge > const & bridge, rtl::OUString const & oid,
73 css::uno::TypeDescription const & type):
74 bridge_(bridge), oid_(oid), type_(type), references_(1)
75 {
76 OSL_ASSERT(bridge.is());
77 acquire = &proxy_acquireInterface;
78 release = &proxy_releaseInterface;
79 pDispatcher = &proxy_dispatchInterface;
80 }
81
getOid() const82 rtl::OUString Proxy::getOid() const {
83 return oid_;
84 }
85
getType() const86 css::uno::TypeDescription Proxy::getType() const {
87 return type_;
88 }
89
do_acquire()90 void Proxy::do_acquire() {
91 if (osl_incrementInterlockedCount(&references_) == 1) {
92 bridge_->resurrectProxy(*this);
93 }
94 }
95
do_release()96 void Proxy::do_release() {
97 if (osl_decrementInterlockedCount(&references_) == 0) {
98 bridge_->revokeProxy(*this);
99 }
100 }
101
do_free()102 void Proxy::do_free() {
103 bridge_->freeProxy(*this);
104 delete this;
105 }
106
do_dispatch(typelib_TypeDescription const * member,void * returnValue,void ** arguments,uno_Any ** exception) const107 void Proxy::do_dispatch(
108 typelib_TypeDescription const * member, void * returnValue,
109 void ** arguments, uno_Any ** exception) const
110 {
111 try {
112 try {
113 do_dispatch_throw(member, returnValue, arguments, exception);
114 } catch (std::exception & e) {
115 throw css::uno::RuntimeException(
116 (rtl::OUString(
117 RTL_CONSTASCII_USTRINGPARAM("caught C++ exception: ")) +
118 rtl::OStringToOUString(
119 rtl::OString(e.what()), RTL_TEXTENCODING_ASCII_US)),
120 css::uno::Reference< css::uno::XInterface >());
121 // best-effort string conversion
122 }
123 } catch (css::uno::RuntimeException &) {
124 css::uno::Any exc(cppu::getCaughtException());
125 uno_copyAndConvertData(
126 *exception, &exc,
127 (css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).
128 get()),
129 bridge_->getCppToBinaryMapping().get());
130 }
131 }
132
isProxy(rtl::Reference<Bridge> const & bridge,css::uno::UnoInterfaceReference const & object,rtl::OUString * oid)133 bool Proxy::isProxy(
134 rtl::Reference< Bridge > const & bridge,
135 css::uno::UnoInterfaceReference const & object, rtl::OUString * oid)
136 {
137 OSL_ASSERT(object.is());
138 return object.m_pUnoI->acquire == &proxy_acquireInterface &&
139 static_cast< Proxy * >(object.m_pUnoI)->isProxy(bridge, oid);
140 }
141
~Proxy()142 Proxy::~Proxy() {}
143
do_dispatch_throw(typelib_TypeDescription const * member,void * returnValue,void ** arguments,uno_Any ** exception) const144 void Proxy::do_dispatch_throw(
145 typelib_TypeDescription const * member, void * returnValue,
146 void ** arguments, uno_Any ** exception) const
147 {
148 //TODO: Optimize queryInterface:
149 OSL_ASSERT(member != 0);
150 bool setter = false;
151 std::vector< BinaryAny > inArgs;
152 switch (member->eTypeClass) {
153 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
154 setter = returnValue == 0;
155 if (setter) {
156 inArgs.push_back(
157 BinaryAny(
158 css::uno::TypeDescription(
159 reinterpret_cast<
160 typelib_InterfaceAttributeTypeDescription const * >(
161 member)->
162 pAttributeTypeRef),
163 arguments[0]));
164 }
165 break;
166 case typelib_TypeClass_INTERFACE_METHOD:
167 {
168 typelib_InterfaceMethodTypeDescription const * mtd =
169 reinterpret_cast<
170 typelib_InterfaceMethodTypeDescription const * >(member);
171 for (sal_Int32 i = 0; i != mtd->nParams; ++i) {
172 if (mtd->pParams[i].bIn) {
173 inArgs.push_back(
174 BinaryAny(
175 css::uno::TypeDescription(mtd->pParams[i].pTypeRef),
176 arguments[i]));
177 }
178 }
179 break;
180 }
181 default:
182 OSL_ASSERT(false); // this cannot happen
183 break;
184 }
185 BinaryAny ret;
186 std::vector< BinaryAny > outArgs;
187 if (bridge_->makeCall(
188 oid_,
189 css::uno::TypeDescription(
190 const_cast< typelib_TypeDescription * >(member)),
191 setter, inArgs, &ret, &outArgs))
192 {
193 OSL_ASSERT(
194 ret.getType().get()->eTypeClass == typelib_TypeClass_EXCEPTION);
195 uno_any_construct(
196 *exception, ret.getValue(ret.getType()), ret.getType().get(), 0);
197 } else {
198 switch (member->eTypeClass) {
199 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
200 if (!setter) {
201 css::uno::TypeDescription t(
202 reinterpret_cast<
203 typelib_InterfaceAttributeTypeDescription const * >(
204 member)->
205 pAttributeTypeRef);
206 uno_copyData(returnValue, ret.getValue(t), t.get(), 0);
207 }
208 break;
209 case typelib_TypeClass_INTERFACE_METHOD:
210 {
211 typelib_InterfaceMethodTypeDescription const * mtd =
212 reinterpret_cast<
213 typelib_InterfaceMethodTypeDescription const * >(
214 member);
215 css::uno::TypeDescription t(mtd->pReturnTypeRef);
216 if (t.get()->eTypeClass != typelib_TypeClass_VOID) {
217 uno_copyData(returnValue, ret.getValue(t), t.get(), 0);
218 }
219 std::vector< BinaryAny >::iterator i(outArgs.begin());
220 for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
221 if (mtd->pParams[j].bOut) {
222 css::uno::TypeDescription pt(mtd->pParams[j].pTypeRef);
223 if (mtd->pParams[j].bIn) {
224 uno_assignData(
225 arguments[j], pt.get(), i++->getValue(pt),
226 pt.get(), 0, 0, 0);
227 } else {
228 uno_copyData(
229 arguments[j], i++->getValue(pt), pt.get(), 0);
230 }
231 }
232 }
233 OSL_ASSERT(i == outArgs.end());
234 break;
235 }
236 default:
237 OSL_ASSERT(false); // this cannot happen
238 break;
239 }
240 *exception = 0;
241 }
242 }
243
isProxy(rtl::Reference<Bridge> const & bridge,rtl::OUString * oid) const244 bool Proxy::isProxy(
245 rtl::Reference< Bridge > const & bridge, rtl::OUString * oid) const
246 {
247 OSL_ASSERT(oid != 0);
248 if (bridge == bridge_) {
249 *oid = oid_;
250 return true;
251 } else {
252 return false;
253 }
254 }
255
256 }
257