delay, collect and compress LOK invalidations for Writer views
[LibreOffice.git] / binaryurp / source / incomingrequest.cxx
blobd75a61e46245094443ae2b775fc04fb2b2b9d855
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <cassert>
23 #include <vector>
25 #include <com/sun/star/bridge/XInstanceProvider.hpp>
26 #include <com/sun/star/container/NoSuchElementException.hpp>
27 #include <cppuhelper/exc_hlp.hxx>
28 #include <o3tl/runtimetooustring.hxx>
29 #include <rtl/byteseq.hxx>
30 #include <rtl/ref.hxx>
31 #include <rtl/ustring.hxx>
32 #include <sal/log.hxx>
33 #include <sal/types.h>
34 #include <typelib/typedescription.hxx>
35 #include <uno/dispatcher.hxx>
37 #include "binaryany.hxx"
38 #include "bridge.hxx"
39 #include "currentcontext.hxx"
40 #include "incomingrequest.hxx"
41 #include "specialfunctionids.hxx"
43 namespace binaryurp {
45 IncomingRequest::IncomingRequest(
46 rtl::Reference< Bridge > const & bridge, rtl::ByteSequence const & tid,
47 OUString const & oid, css::uno::UnoInterfaceReference const & object,
48 css::uno::TypeDescription const & type, sal_uInt16 functionId,
49 bool synchronous, css::uno::TypeDescription const & member, bool setter,
50 std::vector< BinaryAny >&& inArguments, bool currentContextMode,
51 css::uno::UnoInterfaceReference const & currentContext):
52 bridge_(bridge), tid_(tid), oid_(oid), object_(object), type_(type),
53 member_(member), currentContext_(currentContext),
54 inArguments_(std::move(inArguments)), functionId_(functionId),
55 synchronous_(synchronous), setter_(setter), currentContextMode_(currentContextMode)
57 assert(bridge.is());
58 assert(member.is());
59 assert(member.get()->bComplete);
62 IncomingRequest::~IncomingRequest() {}
64 void IncomingRequest::execute() const {
65 BinaryAny ret;
66 std::vector< BinaryAny > outArgs;
67 bool isExc;
68 try {
69 bool resetCc = false;
70 css::uno::UnoInterfaceReference oldCc;
71 if (currentContextMode_) {
72 oldCc = current_context::get();
73 current_context::set(currentContext_);
74 resetCc = true;
76 try {
77 try {
78 isExc = !execute_throw(&ret, &outArgs);
79 } catch (const std::exception & e) {
80 throw css::uno::RuntimeException(
81 "caught C++ exception: "
82 + o3tl::runtimeToOUString(e.what()));
84 } catch (const css::uno::RuntimeException &) {
85 css::uno::Any exc(cppu::getCaughtException());
86 ret = bridge_->mapCppToBinaryAny(exc);
87 isExc = true;
89 if (resetCc) {
90 current_context::set(oldCc);
92 } catch (const css::uno::RuntimeException &) {
93 css::uno::Any exc(cppu::getCaughtException());
94 ret = bridge_->mapCppToBinaryAny(exc);
95 isExc = true;
97 if (synchronous_) {
98 bridge_->decrementActiveCalls();
99 try {
100 bridge_->getWriter()->queueReply(
101 tid_, member_, setter_, isExc, ret, std::move(outArgs), false);
102 return;
103 } catch (const css::uno::RuntimeException & e) {
104 SAL_INFO("binaryurp", "caught " << e);
105 } catch (const std::exception & e) {
106 SAL_INFO("binaryurp", "caught C++ exception " << e.what());
108 bridge_->terminate(false);
109 } else {
110 if (isExc) {
111 SAL_INFO("binaryurp", "oneway method raised exception");
113 bridge_->decrementCalls();
117 static size_t size_t_round(size_t val)
119 return (val + (sizeof(size_t)-1)) & ~(sizeof(size_t)-1);
122 bool IncomingRequest::execute_throw(
123 BinaryAny * returnValue, std::vector< BinaryAny > * outArguments) const
125 assert(returnValue != nullptr);
126 assert(
127 returnValue->getType().equals(
128 css::uno::TypeDescription(cppu::UnoType<void>::get())));
129 assert(outArguments != nullptr);
130 assert(outArguments->empty());
131 bool isExc = false;
132 switch (functionId_) {
133 case SPECIAL_FUNCTION_ID_RESERVED:
134 assert(false); // this cannot happen
135 break;
136 case SPECIAL_FUNCTION_ID_RELEASE:
137 bridge_->releaseStub(oid_, type_);
138 break;
139 case SPECIAL_FUNCTION_ID_QUERY_INTERFACE:
140 if (!object_.is()) {
141 css::uno::Reference< css::uno::XInterface > ifc;
142 css::uno::Reference< css::bridge::XInstanceProvider > prov(
143 bridge_->getProvider());
144 if (prov.is()) {
145 try {
146 ifc = prov->getInstance(oid_);
147 } catch (const css::container::NoSuchElementException & e) {
148 SAL_INFO("binaryurp", "initial element " << oid_ << ": " << e);
151 if (ifc.is()) {
152 css::uno::UnoInterfaceReference unoIfc(
153 static_cast< uno_Interface * >(
154 bridge_->getCppToBinaryMapping().mapInterface(
155 ifc.get(),
156 (css::uno::TypeDescription(
157 cppu::UnoType<
158 css::uno::Reference<
159 css::uno::XInterface > >::get()).
160 get()))),
161 SAL_NO_ACQUIRE);
162 *returnValue = BinaryAny(
163 css::uno::TypeDescription(
164 cppu::UnoType<
165 css::uno::Reference<
166 css::uno::XInterface > >::get()),
167 &unoIfc.m_pUnoI);
169 break;
171 [[fallthrough]];
172 default:
174 assert(object_.is());
175 css::uno::TypeDescription retType;
176 std::vector< std::vector< char > > outBufs;
177 std::vector< void * > args;
178 switch (member_.get()->eTypeClass) {
179 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
181 css::uno::TypeDescription t(
182 reinterpret_cast<
183 typelib_InterfaceAttributeTypeDescription * >(
184 member_.get())->
185 pAttributeTypeRef);
186 if (setter_) {
187 assert(inArguments_.size() == 1);
188 args.push_back(inArguments_[0].getValue(t));
189 } else {
190 assert(inArguments_.empty());
191 retType = t;
193 break;
195 case typelib_TypeClass_INTERFACE_METHOD:
197 typelib_InterfaceMethodTypeDescription * mtd =
198 reinterpret_cast<
199 typelib_InterfaceMethodTypeDescription * >(
200 member_.get());
201 retType = css::uno::TypeDescription(mtd->pReturnTypeRef);
202 std::vector< BinaryAny >::const_iterator i(
203 inArguments_.begin());
204 for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
205 void * p;
206 if (mtd->pParams[j].bIn) {
207 p = i++->getValue(
208 css::uno::TypeDescription(
209 mtd->pParams[j].pTypeRef));
210 } else {
211 outBufs.emplace_back(size_t_round(
212 css::uno::TypeDescription(
213 mtd->pParams[j].pTypeRef).
214 get()->nSize));
215 p = outBufs.back().data();
217 args.push_back(p);
218 if (mtd->pParams[j].bOut) {
219 outArguments->push_back(BinaryAny());
222 assert(i == inArguments_.end());
223 break;
225 default:
226 assert(false); // this cannot happen
227 break;
229 size_t nSize = 0;
230 if (retType.is())
231 nSize = size_t_round(retType.get()->nSize);
232 std::vector< char > retBuf(nSize);
233 uno_Any exc;
234 uno_Any * pexc = &exc;
235 (*object_.get()->pDispatcher)(
236 object_.get(), member_.get(), retBuf.empty() ? nullptr : retBuf.data(),
237 args.empty() ? nullptr : args.data(), &pexc);
238 isExc = pexc != nullptr;
239 if (isExc) {
240 *returnValue = BinaryAny(
241 css::uno::TypeDescription(
242 cppu::UnoType< css::uno::Any >::get()),
243 &exc);
244 uno_any_destruct(&exc, nullptr);
245 } else {
246 if (!retBuf.empty()) {
247 *returnValue = BinaryAny(retType, retBuf.data());
248 uno_destructData(retBuf.data(), retType.get(), nullptr);
250 if (!outArguments->empty()) {
251 assert(
252 member_.get()->eTypeClass ==
253 typelib_TypeClass_INTERFACE_METHOD);
254 typelib_InterfaceMethodTypeDescription * mtd =
255 reinterpret_cast<
256 typelib_InterfaceMethodTypeDescription * >(
257 member_.get());
258 std::vector< BinaryAny >::iterator i(outArguments->begin());
259 std::vector< std::vector< char > >::iterator j(
260 outBufs.begin());
261 for (sal_Int32 k = 0; k != mtd->nParams; ++k) {
262 if (mtd->pParams[k].bOut) {
263 *i++ = BinaryAny(
264 css::uno::TypeDescription(
265 mtd->pParams[k].pTypeRef),
266 args[k]);
268 if (!mtd->pParams[k].bIn) {
269 uno_type_destructData(
270 (j++)->data(), mtd->pParams[k].pTypeRef, nullptr);
273 assert(i == outArguments->end());
274 assert(j == outBufs.end());
277 break;
280 return !isExc;
285 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */