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