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 <list>
27 #include <vector>
28
29 #include "boost/noncopyable.hpp"
30 #include "com/sun/star/bridge/XInstanceProvider.hpp"
31 #include "cppuhelper/exc_hlp.hxx"
32 #include "rtl/byteseq.hxx"
33 #include "rtl/ref.hxx"
34 #include "rtl/ustring.hxx"
35 #include "sal/types.h"
36 #include "typelib/typedescription.hxx"
37 #include "uno/dispatcher.hxx"
38
39 #include "binaryany.hxx"
40 #include "bridge.hxx"
41 #include "currentcontext.hxx"
42 #include "incomingrequest.hxx"
43 #include "specialfunctionids.hxx"
44
45 namespace binaryurp {
46
47 namespace {
48
49 namespace css = com::sun::star;
50
51 }
52
IncomingRequest(rtl::Reference<Bridge> const & bridge,rtl::ByteSequence const & tid,rtl::OUString const & oid,css::uno::UnoInterfaceReference const & object,css::uno::TypeDescription const & type,sal_uInt16 functionId,bool synchronous,css::uno::TypeDescription const & member,bool setter,std::vector<BinaryAny> const & inArguments,bool currentContextMode,css::uno::UnoInterfaceReference const & currentContext)53 IncomingRequest::IncomingRequest(
54 rtl::Reference< Bridge > const & bridge, rtl::ByteSequence const & tid,
55 rtl::OUString const & oid, css::uno::UnoInterfaceReference const & object,
56 css::uno::TypeDescription const & type, sal_uInt16 functionId,
57 bool synchronous, css::uno::TypeDescription const & member, bool setter,
58 std::vector< BinaryAny > const & inArguments, bool currentContextMode,
59 css::uno::UnoInterfaceReference const & currentContext):
60 bridge_(bridge), tid_(tid), oid_(oid), object_(object), type_(type),
61 functionId_(functionId), synchronous_(synchronous), member_(member),
62 setter_(setter), inArguments_(inArguments),
63 currentContextMode_(currentContextMode), currentContext_(currentContext)
64 {
65 OSL_ASSERT(bridge.is() && member.is() && member.get()->bComplete);
66 }
67
~IncomingRequest()68 IncomingRequest::~IncomingRequest() {}
69
execute() const70 void IncomingRequest::execute() const {
71 BinaryAny ret;
72 std::vector< BinaryAny > outArgs;
73 bool isExc;
74 try {
75 bool resetCc = false;
76 css::uno::UnoInterfaceReference oldCc;
77 if (currentContextMode_) {
78 oldCc = current_context::get();
79 current_context::set(currentContext_);
80 resetCc = true;
81 }
82 try {
83 try {
84 isExc = !execute_throw(&ret, &outArgs);
85 } catch (std::exception & e) {
86 throw css::uno::RuntimeException(
87 (rtl::OUString(
88 RTL_CONSTASCII_USTRINGPARAM("caught C++ exception: ")) +
89 rtl::OStringToOUString(
90 rtl::OString(e.what()), RTL_TEXTENCODING_ASCII_US)),
91 css::uno::Reference< css::uno::XInterface >());
92 // best-effort string conversion
93 }
94 } catch (css::uno::RuntimeException &) {
95 css::uno::Any exc(cppu::getCaughtException());
96 ret = bridge_->mapCppToBinaryAny(exc);
97 isExc = true;
98 }
99 if (resetCc) {
100 current_context::set(oldCc);
101 }
102 } catch (css::uno::RuntimeException &) {
103 css::uno::Any exc(cppu::getCaughtException());
104 ret = bridge_->mapCppToBinaryAny(exc);
105 isExc = true;
106 }
107 if (synchronous_) {
108 bridge_->decrementActiveCalls();
109 try {
110 bridge_->getWriter()->queueReply(
111 tid_, member_, setter_, isExc, ret, outArgs, false);
112 return;
113 } catch (css::uno::RuntimeException & e) {
114 OSL_TRACE(
115 OSL_LOG_PREFIX "caught UNO runtime exception '%s'",
116 (rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).
117 getStr()));
118 } catch (std::exception & e) {
119 OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
120 }
121 bridge_->terminate();
122 } else {
123 if (isExc) {
124 OSL_TRACE(OSL_LOG_PREFIX "oneway method raised exception");
125 }
126 bridge_->decrementCalls();
127 }
128 }
129
execute_throw(BinaryAny * returnValue,std::vector<BinaryAny> * outArguments) const130 bool IncomingRequest::execute_throw(
131 BinaryAny * returnValue, std::vector< BinaryAny > * outArguments) const
132 {
133 OSL_ASSERT(
134 returnValue != 0 &&
135 returnValue->getType().equals(
136 css::uno::TypeDescription(
137 cppu::UnoType< cppu::UnoVoidType >::get())) &&
138 outArguments != 0 && outArguments->empty());
139 bool isExc = false;
140 switch (functionId_) {
141 case SPECIAL_FUNCTION_ID_RESERVED:
142 OSL_ASSERT(false); // this cannot happen
143 break;
144 case SPECIAL_FUNCTION_ID_RELEASE:
145 bridge_->releaseStub(oid_, type_);
146 break;
147 case SPECIAL_FUNCTION_ID_QUERY_INTERFACE:
148 if (!object_.is()) {
149 css::uno::Reference< css::uno::XInterface > ifc;
150 css::uno::Reference< css::bridge::XInstanceProvider > prov(
151 bridge_->getProvider());
152 if (prov.is()) {
153 try {
154 ifc = prov->getInstance(oid_);
155 } catch (css::container::NoSuchElementException & e) {
156 OSL_TRACE(
157 (OSL_LOG_PREFIX "initial element '%s':"
158 " NoSuchElementException '%s'"),
159 (rtl::OUStringToOString(oid_, RTL_TEXTENCODING_UTF8).
160 getStr()),
161 (rtl::OUStringToOString(
162 e.Message, RTL_TEXTENCODING_UTF8).
163 getStr()));
164 }
165 }
166 if (ifc.is()) {
167 css::uno::UnoInterfaceReference unoIfc(
168 static_cast< uno_Interface * >(
169 bridge_->getCppToBinaryMapping().mapInterface(
170 ifc.get(),
171 (css::uno::TypeDescription(
172 cppu::UnoType<
173 css::uno::Reference<
174 css::uno::XInterface > >::get()).
175 get()))),
176 SAL_NO_ACQUIRE);
177 *returnValue = BinaryAny(
178 css::uno::TypeDescription(
179 cppu::UnoType<
180 css::uno::Reference<
181 css::uno::XInterface > >::get()),
182 &unoIfc.m_pUnoI);
183 }
184 break;
185 }
186 // fall through
187 default:
188 {
189 OSL_ASSERT(object_.is());
190 css::uno::TypeDescription retType;
191 std::list< std::vector< char > > outBufs;
192 std::vector< void * > args;
193 switch (member_.get()->eTypeClass) {
194 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
195 {
196 css::uno::TypeDescription t(
197 reinterpret_cast<
198 typelib_InterfaceAttributeTypeDescription * >(
199 member_.get())->
200 pAttributeTypeRef);
201 if (setter_) {
202 OSL_ASSERT(inArguments_.size() == 1);
203 args.push_back(inArguments_[0].getValue(t));
204 } else {
205 OSL_ASSERT(inArguments_.empty());
206 retType = t;
207 }
208 break;
209 }
210 case typelib_TypeClass_INTERFACE_METHOD:
211 {
212 typelib_InterfaceMethodTypeDescription * mtd =
213 reinterpret_cast<
214 typelib_InterfaceMethodTypeDescription * >(
215 member_.get());
216 retType = css::uno::TypeDescription(mtd->pReturnTypeRef);
217 std::vector< BinaryAny >::const_iterator i(
218 inArguments_.begin());
219 for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
220 void * p;
221 if (mtd->pParams[j].bIn) {
222 p = i++->getValue(
223 css::uno::TypeDescription(
224 mtd->pParams[j].pTypeRef));
225 } else {
226 outBufs.push_back(
227 std::vector< char >(
228 css::uno::TypeDescription(
229 mtd->pParams[j].pTypeRef).
230 get()->nSize));
231 p = &outBufs.back()[0];
232 }
233 args.push_back(p);
234 if (mtd->pParams[j].bOut) {
235 outArguments->push_back(BinaryAny());
236 }
237 }
238 OSL_ASSERT(i == inArguments_.end());
239 break;
240 }
241 default:
242 OSL_ASSERT(false); // this cannot happen
243 break;
244 }
245 std::vector< char > retBuf(retType.is() ? retType.get()->nSize : 0);
246 uno_Any exc;
247 uno_Any * pexc = &exc;
248 (*object_.get()->pDispatcher)(
249 object_.get(), member_.get(), retBuf.empty() ? 0 : &retBuf[0],
250 args.empty() ? 0 : &args[0], &pexc);
251 isExc = pexc != 0;
252 if (isExc) {
253 *returnValue = BinaryAny(
254 css::uno::TypeDescription(
255 cppu::UnoType< css::uno::Any >::get()),
256 &exc);
257 uno_any_destruct(&exc, 0);
258 } else {
259 if (!retBuf.empty()) {
260 *returnValue = BinaryAny(retType, &retBuf[0]);
261 uno_destructData(&retBuf[0], retType.get(), 0);
262 }
263 if (!outArguments->empty()) {
264 OSL_ASSERT(
265 member_.get()->eTypeClass ==
266 typelib_TypeClass_INTERFACE_METHOD);
267 typelib_InterfaceMethodTypeDescription * mtd =
268 reinterpret_cast<
269 typelib_InterfaceMethodTypeDescription * >(
270 member_.get());
271 std::vector< BinaryAny >::iterator i(outArguments->begin());
272 std::list< std::vector< char > >::iterator j(
273 outBufs.begin());
274 for (sal_Int32 k = 0; k != mtd->nParams; ++k) {
275 if (mtd->pParams[k].bOut) {
276 *i++ = BinaryAny(
277 css::uno::TypeDescription(
278 mtd->pParams[k].pTypeRef),
279 args[k]);
280 }
281 if (!mtd->pParams[k].bIn) {
282 uno_type_destructData(
283 &(*j++)[0], mtd->pParams[k].pTypeRef, 0);
284 }
285 }
286 OSL_ASSERT(i == outArguments->end());
287 OSL_ASSERT(j == outBufs.end());
288 }
289 }
290 break;
291 }
292 }
293 return !isExc;
294 }
295
296 }
297