Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : : #include "sal/config.h"
21 : :
22 : : #include <algorithm>
23 : : #include <cassert>
24 : : #include <cstddef>
25 : : #include <limits>
26 : : #include <memory>
27 : : #include <vector>
28 : :
29 : : #include "boost/noncopyable.hpp"
30 : : #include "com/sun/star/bridge/InvalidProtocolChangeException.hpp"
31 : : #include "com/sun/star/bridge/XBridge.hpp"
32 : : #include "com/sun/star/bridge/XInstanceProvider.hpp"
33 : : #include "com/sun/star/bridge/XProtocolProperties.hpp"
34 : : #include "com/sun/star/connection/XConnection.hpp"
35 : : #include "com/sun/star/io/IOException.hpp"
36 : : #include "com/sun/star/lang/DisposedException.hpp"
37 : : #include "com/sun/star/lang/EventObject.hpp"
38 : : #include "com/sun/star/lang/XEventListener.hpp"
39 : : #include "com/sun/star/uno/Reference.hxx"
40 : : #include "com/sun/star/uno/RuntimeException.hpp"
41 : : #include "com/sun/star/uno/Sequence.hxx"
42 : : #include "com/sun/star/uno/XInterface.hpp"
43 : : #include "cppuhelper/exc_hlp.hxx"
44 : : #include "cppuhelper/weak.hxx"
45 : : #include "osl/mutex.hxx"
46 : : #include "osl/thread.hxx"
47 : : #include "rtl/byteseq.hxx"
48 : : #include "rtl/oustringostreaminserter.hxx"
49 : : #include "rtl/random.h"
50 : : #include "rtl/ref.hxx"
51 : : #include "rtl/ustrbuf.hxx"
52 : : #include "rtl/ustring.h"
53 : : #include "rtl/ustring.hxx"
54 : : #include "sal/log.hxx"
55 : : #include "sal/types.h"
56 : : #include "typelib/typeclass.h"
57 : : #include "typelib/typedescription.h"
58 : : #include "typelib/typedescription.hxx"
59 : : #include "uno/dispatcher.hxx"
60 : : #include "uno/environment.hxx"
61 : : #include "uno/lbnames.h"
62 : :
63 : : #include "binaryany.hxx"
64 : : #include "bridge.hxx"
65 : : #include "bridgefactory.hxx"
66 : : #include "incomingreply.hxx"
67 : : #include "lessoperators.hxx"
68 : : #include "outgoingrequest.hxx"
69 : : #include "outgoingrequests.hxx"
70 : : #include "proxy.hxx"
71 : : #include "reader.hxx"
72 : :
73 : : namespace binaryurp {
74 : :
75 : : namespace {
76 : :
77 : : namespace css = com::sun::star;
78 : :
79 : 102 : sal_Int32 random() {
80 : : sal_Int32 n;
81 : 102 : rtlRandomPool pool = rtl_random_createPool();
82 : 102 : rtl_random_getBytes(pool, &n, sizeof n);
83 : 102 : rtl_random_destroyPool(pool);
84 : 102 : return n;
85 : : }
86 : :
87 : 0 : OUString toString(css::uno::TypeDescription const & type) {
88 : 0 : typelib_TypeDescription * d = type.get();
89 : : assert(d != 0 && d->pTypeName != 0);
90 : 0 : return OUString(d->pTypeName);
91 : : }
92 : :
93 : 3800 : extern "C" void SAL_CALL freeProxyCallback(
94 : : SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pProxy)
95 : : {
96 : : assert(pProxy != 0);
97 : 3800 : static_cast< Proxy * >(pProxy)->do_free();
98 : 3800 : }
99 : :
100 : 200 : bool isThread(salhelper::Thread * thread) {
101 : : assert(thread != 0);
102 : 200 : return osl::Thread::getCurrentIdentifier() == thread->getIdentifier();
103 : : }
104 : :
105 : : class AttachThread: private boost::noncopyable {
106 : : public:
107 : : explicit AttachThread(uno_ThreadPool threadPool);
108 : :
109 : : ~AttachThread();
110 : :
111 : : rtl::ByteSequence getTid() throw ();
112 : :
113 : : private:
114 : : uno_ThreadPool threadPool_;
115 : : rtl::ByteSequence tid_;
116 : : };
117 : :
118 : 22782 : AttachThread::AttachThread(uno_ThreadPool threadPool): threadPool_(threadPool) {
119 : 22782 : sal_Sequence * s = 0;
120 : 22782 : uno_getIdOfCurrentThread(&s);
121 : 22782 : tid_ = rtl::ByteSequence(s, rtl::BYTESEQ_NOACQUIRE);
122 : 22782 : uno_threadpool_attach(threadPool_);
123 : 22782 : }
124 : :
125 : 22782 : AttachThread::~AttachThread() {
126 : 22782 : uno_threadpool_detach(threadPool_);
127 : 22782 : uno_releaseIdFromCurrentThread();
128 : 22782 : }
129 : :
130 : 36388 : rtl::ByteSequence AttachThread::getTid() throw () {
131 : 36388 : return tid_;
132 : : }
133 : :
134 : : class PopOutgoingRequest: private boost::noncopyable {
135 : : public:
136 : : PopOutgoingRequest(
137 : : OutgoingRequests & requests, rtl::ByteSequence const & tid,
138 : : OutgoingRequest const & request);
139 : :
140 : : ~PopOutgoingRequest();
141 : :
142 : : void clear();
143 : :
144 : : private:
145 : : OutgoingRequests & requests_;
146 : : rtl::ByteSequence tid_;
147 : : bool cleared_;
148 : : };
149 : :
150 : 13767 : PopOutgoingRequest::PopOutgoingRequest(
151 : : OutgoingRequests & requests, rtl::ByteSequence const & tid,
152 : : OutgoingRequest const & request):
153 : 13767 : requests_(requests), tid_(tid), cleared_(false)
154 : : {
155 [ + - ]: 13767 : requests_.push(tid_, request);
156 : 13767 : }
157 : :
158 : 13767 : PopOutgoingRequest::~PopOutgoingRequest() {
159 [ - + ]: 13767 : if (!cleared_) {
160 : 0 : requests_.pop(tid_);
161 : : }
162 : 13767 : }
163 : :
164 : 13767 : void PopOutgoingRequest::clear() {
165 : 13767 : cleared_ = true;
166 : 13767 : }
167 : :
168 : : }
169 : :
170 : 589890 : struct Bridge::SubStub {
171 : : com::sun::star::uno::UnoInterfaceReference object;
172 : :
173 : : sal_uInt32 references;
174 : : };
175 : :
176 : 102 : Bridge::Bridge(
177 : : rtl::Reference< BridgeFactory > const & factory, OUString const & name,
178 : : css::uno::Reference< css::connection::XConnection > const & connection,
179 : : css::uno::Reference< css::bridge::XInstanceProvider > const & provider):
180 : : factory_(factory), name_(name), connection_(connection),
181 : : provider_(provider),
182 : : binaryUno_(OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO))),
183 : : cppToBinaryMapping_(
184 : : OUString(
185 : : RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME)),
186 : : OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO))),
187 : : binaryToCppMapping_(
188 : : OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)),
189 : : OUString(
190 : : RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME))),
191 : : protPropTid_(
192 : : reinterpret_cast< sal_Int8 const * >(".UrpProtocolPropertiesTid"),
193 : : RTL_CONSTASCII_LENGTH(".UrpProtocolPropertiesTid")),
194 : : protPropOid_(RTL_CONSTASCII_USTRINGPARAM("UrpProtocolProperties")),
195 : : protPropType_(
196 : : cppu::UnoType<
197 [ + - ]: 102 : css::uno::Reference< css::bridge::XProtocolProperties > >::get()),
198 : : protPropRequest_(
199 : : OUString(
200 : : RTL_CONSTASCII_USTRINGPARAM(
201 : : "com.sun.star.bridge.XProtocolProperties::requestChange"))),
202 : : protPropCommit_(
203 : : OUString(
204 : : RTL_CONSTASCII_USTRINGPARAM(
205 : : "com.sun.star.bridge.XProtocolProperties::commitChange"))),
206 : : state_(STATE_INITIAL), threadPool_(0), currentContextMode_(false),
207 : : proxies_(0), calls_(0), normalCall_(false), activeCalls_(0),
208 [ + - ][ + - ]: 204 : mode_(MODE_REQUESTED)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
209 : : {
210 : : assert(factory.is() && connection.is());
211 [ - + ]: 102 : if (!binaryUno_.is()) {
212 : : throw css::uno::RuntimeException(
213 : : OUString(
214 : : RTL_CONSTASCII_USTRINGPARAM("URP: no binary UNO environment")),
215 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
216 : : }
217 [ + - ][ - + ]: 102 : if (!(cppToBinaryMapping_.is() && binaryToCppMapping_.is())) {
[ - + ]
218 : : throw css::uno::RuntimeException(
219 : : OUString(
220 : : RTL_CONSTASCII_USTRINGPARAM("URP: no C++ UNO mapping")),
221 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
222 : : }
223 [ + - ]: 102 : passive_.set();
224 : 102 : }
225 : :
226 : 102 : void Bridge::start() {
227 [ + - ][ + - ]: 102 : rtl::Reference< Reader > r(new Reader(this));
[ + - ]
228 [ + - ][ + - ]: 102 : rtl::Reference< Writer > w(new Writer(this));
[ + - ]
229 : : {
230 [ + - ]: 102 : osl::MutexGuard g(mutex_);
231 : : assert(
232 : : state_ == STATE_INITIAL && threadPool_ == 0 && !writer_.is() &&
233 : : !reader_.is());
234 : 102 : threadPool_ = uno_threadpool_create();
235 : : assert(threadPool_ != 0);
236 [ + - ]: 102 : reader_ = r;
237 [ + - ]: 102 : writer_ = w;
238 [ + - ]: 102 : state_ = STATE_STARTED;
239 : : }
240 : : // It is important to call reader_->launch() last here; both
241 : : // Writer::execute and Reader::execute can call Bridge::terminate, but
242 : : // Writer::execute is initially blocked in unblocked_.wait() until
243 : : // Reader::execute has called bridge_->sendRequestChangeRequest(), so
244 : : // effectively only reader_->launch() can lead to an early call to
245 : : // Bridge::terminate
246 [ + - ]: 102 : w->launch();
247 [ + - ][ + - ]: 102 : r->launch();
[ + - ]
248 : 102 : }
249 : :
250 : 320 : void Bridge::terminate(bool final) {
251 : : uno_ThreadPool tp;
252 : : // Make sure function-local variables (Stubs s, etc.) are destroyed before
253 : : // the final uno_threadpool_destroy/threadPool_ = 0:
254 : : {
255 : 320 : rtl::Reference< Reader > r;
256 : 320 : rtl::Reference< Writer > w;
257 : : bool joinW;
258 [ + - ]: 320 : Listeners ls;
259 : : {
260 [ + - ]: 320 : osl::ClearableMutexGuard g(mutex_);
261 [ + + + - ]: 320 : switch (state_) {
262 : : case STATE_INITIAL: // via ~Bridge -> dispose -> terminate
263 : : case STATE_FINAL:
264 : : return;
265 : : case STATE_STARTED:
266 : 100 : break;
267 : : case STATE_TERMINATED:
268 [ + + ]: 8 : if (final) {
269 [ + - ]: 6 : g.clear();
270 [ + - ]: 6 : terminated_.wait();
271 : : {
272 [ + - ]: 6 : osl::MutexGuard g2(mutex_);
273 : 6 : tp = threadPool_;
274 : 6 : threadPool_ = 0;
275 : : assert(!(reader_.is() && isThread(reader_.get())));
276 [ + - ]: 6 : std::swap(reader_, r);
277 : : assert(!(writer_.is() && isThread(writer_.get())));
278 [ + - ]: 6 : std::swap(writer_, w);
279 [ + - ]: 6 : state_ = STATE_FINAL;
280 : : }
281 : : assert(!(r.is() && w.is()));
282 [ + + ]: 6 : if (r.is()) {
283 [ + - ]: 4 : r->join();
284 [ - + ]: 2 : } else if (w.is()) {
285 [ # # ]: 0 : w->join();
286 : : }
287 [ + - ]: 6 : if (tp != 0) {
288 : 8 : uno_threadpool_destroy(tp);
289 : : }
290 : : }
291 : : return;
292 : : }
293 : 100 : tp = threadPool_;
294 : : assert(!(final && isThread(reader_.get())));
295 [ + - ][ + + ]: 100 : if (!isThread(reader_.get())) {
296 [ + - ]: 96 : std::swap(reader_, r);
297 : : }
298 [ + - ]: 100 : w = writer_;
299 [ + - ]: 100 : joinW = !isThread(writer_.get());
300 : : assert(!final || joinW);
301 [ + - ]: 100 : if (joinW) {
302 [ + - ]: 100 : writer_.clear();
303 : : }
304 [ + - ]: 100 : ls.swap(listeners_);
305 [ + + ][ + - ]: 320 : state_ = final ? STATE_FINAL : STATE_TERMINATED;
[ + + # # ]
306 : : }
307 : : try {
308 [ + - ][ + - ]: 320 : connection_->close();
309 [ # # ]: 0 : } catch (const css::io::IOException & e) {
310 : : SAL_INFO("binaryurp", "caught IO exception '" << e.Message << '\'');
311 : : }
312 : : assert(w.is());
313 [ + - ]: 100 : w->stop();
314 [ + + ]: 100 : if (r.is()) {
315 [ + - ]: 96 : r->join();
316 : : }
317 [ + - ]: 100 : if (joinW) {
318 [ + - ]: 100 : w->join();
319 : : }
320 : : assert(tp != 0);
321 : 100 : uno_threadpool_dispose(tp);
322 [ + - ]: 100 : Stubs s;
323 : : {
324 [ + - ]: 100 : osl::MutexGuard g(mutex_);
325 [ + - ][ + - ]: 100 : s.swap(stubs_);
326 : : }
327 [ + + ]: 27499 : for (Stubs::iterator i(s.begin()); i != s.end(); ++i) {
328 [ + + ]: 72382 : for (Stub::iterator j(i->second.begin()); j != i->second.end(); ++j)
329 : : {
330 : : SAL_INFO(
331 : : "binaryurp",
332 : : "stub '" << i->first << "', '" << toString(j->first)
333 : : << "' still mapped at Bridge::terminate");
334 : 44983 : binaryUno_.get()->pExtEnv->revokeInterface(
335 [ + - ]: 44983 : binaryUno_.get()->pExtEnv, j->second.object.get());
336 : : }
337 : : }
338 [ + - ][ + - ]: 100 : factory_->removeBridge(this);
339 [ + + ]: 102 : for (Listeners::iterator i(ls.begin()); i != ls.end(); ++i) {
340 : : try {
341 [ + - ]: 2 : (*i)->disposing(
342 : : css::lang::EventObject(
343 [ + - ][ + - ]: 2 : static_cast< cppu::OWeakObject * >(this)));
[ + - ][ + - ]
[ # # ]
344 [ # # ]: 0 : } catch (const css::uno::RuntimeException & e) {
345 : : SAL_WARN(
346 : : "binaryurp",
347 : : "caught runtime exception '" << e.Message << '\'');
348 : : }
349 [ + + ][ + - ]: 320 : }
[ + + ][ + - ]
[ + + ]
350 : : }
351 [ + + ]: 320 : if (final) {
352 : 94 : uno_threadpool_destroy(tp);
353 : : }
354 : : {
355 [ + - ]: 100 : osl::MutexGuard g(mutex_);
356 [ + + ]: 100 : if (final) {
357 : 94 : threadPool_ = 0;
358 [ + - ]: 100 : }
359 : : }
360 : 320 : terminated_.set();
361 : : }
362 : :
363 : 389903 : css::uno::Reference< css::connection::XConnection > Bridge::getConnection()
364 : : const
365 : : {
366 : 389903 : return connection_;
367 : : }
368 : :
369 : 132 : css::uno::Reference< css::bridge::XInstanceProvider > Bridge::getProvider()
370 : : const
371 : : {
372 : 132 : return provider_;
373 : : }
374 : :
375 : 134 : css::uno::Mapping & Bridge::getCppToBinaryMapping() {
376 : 134 : return cppToBinaryMapping_;
377 : : }
378 : :
379 : 169 : BinaryAny Bridge::mapCppToBinaryAny(css::uno::Any const & cppAny) {
380 : 169 : css::uno::Any in(cppAny);
381 : 169 : BinaryAny out;
382 : 169 : out.~BinaryAny();
383 : : uno_copyAndConvertData(
384 : 169 : out.get(), &in,
385 : 169 : css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).get(),
386 : 507 : cppToBinaryMapping_.get());
387 : 169 : return out;
388 : : }
389 : :
390 : 499604 : uno_ThreadPool Bridge::getThreadPool() {
391 [ + - ]: 499604 : osl::MutexGuard g(mutex_);
392 [ + + ]: 499604 : checkDisposed();
393 : : assert(threadPool_ != 0);
394 [ + - ]: 499604 : return threadPool_;
395 : : }
396 : :
397 : 389913 : rtl::Reference< Writer > Bridge::getWriter() {
398 [ + - ]: 389913 : osl::MutexGuard g(mutex_);
399 [ + + ]: 389913 : checkDisposed();
400 : : assert(writer_.is());
401 [ + - ][ + - ]: 389913 : return writer_;
402 : : }
403 : :
404 : 390161 : css::uno::UnoInterfaceReference Bridge::registerIncomingInterface(
405 : : OUString const & oid, css::uno::TypeDescription const & type)
406 : : {
407 : : assert(type.is());
408 [ + + ]: 390161 : if (oid.isEmpty()) {
409 : 368539 : return css::uno::UnoInterfaceReference();
410 : : }
411 [ + - ]: 21622 : css::uno::UnoInterfaceReference obj(findStub(oid, type));
412 [ + + ]: 21622 : if (!obj.is()) {
413 : 9247 : binaryUno_.get()->pExtEnv->getRegisteredInterface(
414 : 9247 : binaryUno_.get()->pExtEnv,
415 : : reinterpret_cast< void ** >(&obj.m_pUnoI), oid.pData,
416 [ + - ]: 18494 : reinterpret_cast< typelib_InterfaceTypeDescription * >(type.get()));
417 [ + + ]: 9247 : if (obj.is()) {
418 [ + - ]: 5433 : makeReleaseCall(oid, type);
419 : : } else {
420 [ + - ][ + - ]: 3814 : obj.set(new Proxy(this, oid, type), SAL_NO_ACQUIRE);
[ + - ]
421 : : {
422 [ + - ]: 3814 : osl::MutexGuard g(mutex_);
423 : : assert(proxies_ < std::numeric_limits< std::size_t >::max());
424 [ + - ]: 3814 : ++proxies_;
425 : : }
426 : 3814 : binaryUno_.get()->pExtEnv->registerProxyInterface(
427 : 3814 : binaryUno_.get()->pExtEnv,
428 : : reinterpret_cast< void ** >(&obj.m_pUnoI), &freeProxyCallback,
429 : : oid.pData,
430 : : reinterpret_cast< typelib_InterfaceTypeDescription * >(
431 [ + - ]: 7628 : type.get()));
432 : : }
433 : : }
434 [ + - ][ + - ]: 390161 : return obj;
435 : : }
436 : :
437 : 157800 : OUString Bridge::registerOutgoingInterface(
438 : : css::uno::UnoInterfaceReference const & object,
439 : : css::uno::TypeDescription const & type)
440 : : {
441 : : assert(type.is());
442 [ + + ]: 157800 : if (!object.is()) {
443 : 16216 : return OUString();
444 : : }
445 : 141584 : OUString oid;
446 [ + + ][ + - ]: 141584 : if (!Proxy::isProxy(this, object, &oid)) {
447 : 141320 : binaryUno_.get()->pExtEnv->getObjectIdentifier(
448 [ + - ]: 141320 : binaryUno_.get()->pExtEnv, &oid.pData, object.get());
449 [ + - ]: 141320 : osl::MutexGuard g(mutex_);
450 [ + - ]: 141320 : Stubs::iterator i(stubs_.find(oid));
451 [ + - ]: 141320 : Stub newStub;
452 [ + + ]: 141320 : Stub * stub = i == stubs_.end() ? &newStub : &i->second;
453 [ + - ]: 141320 : Stub::iterator j(stub->find(type));
454 : : //TODO: Release sub-stub if it is not successfully sent to remote side
455 : : // (otherwise, stub will leak until terminate()):
456 [ + + ]: 141320 : if (j == stub->end()) {
457 [ + - ][ + - ]: 98316 : j = stub->insert(Stub::value_type(type, SubStub())).first;
[ + - ][ + - ]
[ + - ]
458 [ + + ]: 98316 : if (stub == &newStub) {
459 [ + - ][ + - ]: 63329 : i = stubs_.insert(Stubs::value_type(oid, Stub())).first;
460 [ + - ]: 63329 : std::swap(i->second, newStub);
461 [ + - ]: 63329 : j = i->second.find(type);
462 : : assert(j != i->second.end());
463 : : }
464 [ + - ]: 98316 : j->second.object = object;
465 : 98316 : j->second.references = 1;
466 : 98316 : binaryUno_.get()->pExtEnv->registerInterface(
467 : 98316 : binaryUno_.get()->pExtEnv,
468 : 98316 : reinterpret_cast< void ** >(&j->second.object.m_pUnoI),
469 : : oid.pData,
470 : : reinterpret_cast< typelib_InterfaceTypeDescription * >(
471 [ + - ]: 196632 : type.get()));
472 : : } else {
473 : : assert(stub != &newStub);
474 [ - + ]: 43004 : if (j->second.references == SAL_MAX_UINT32) {
475 : : throw css::uno::RuntimeException(
476 : : OUString(
477 : : RTL_CONSTASCII_USTRINGPARAM(
478 : : "URP: stub reference count overflow")),
479 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
480 : : }
481 : 43004 : ++j->second.references;
482 [ + - ]: 141320 : }
483 : : }
484 : 157800 : return oid;
485 : : }
486 : :
487 : 388345 : css::uno::UnoInterfaceReference Bridge::findStub(
488 : : OUString const & oid, css::uno::TypeDescription const & type)
489 : : {
490 : : assert(!oid.isEmpty() && type.is());
491 [ + - ]: 388345 : osl::MutexGuard g(mutex_);
492 [ + - ]: 388345 : Stubs::iterator i(stubs_.find(oid));
493 [ + + ]: 388345 : if (i != stubs_.end()) {
494 [ + - ]: 378966 : Stub::iterator j(i->second.find(type));
495 [ + + ]: 378966 : if (j != i->second.end()) {
496 [ + - ]: 372830 : return j->second.object;
497 : : }
498 [ + - ]: 385246 : for (j = i->second.begin(); j != i->second.end(); ++j) {
499 [ + + ]: 6280 : if (typelib_typedescription_isAssignableFrom(
500 : 6280 : type.get(), j->first.get()))
501 : : {
502 [ + - ]: 6136 : return j->second.object;
503 : : }
504 : : }
505 : : }
506 [ + - ]: 388345 : return css::uno::UnoInterfaceReference();
507 : : }
508 : :
509 : 96434 : void Bridge::releaseStub(
510 : : OUString const & oid, css::uno::TypeDescription const & type)
511 : : {
512 : : assert(!oid.isEmpty() && type.is());
513 : 96434 : css::uno::UnoInterfaceReference obj;
514 : : bool unused;
515 : : {
516 [ + - ]: 96434 : osl::MutexGuard g(mutex_);
517 [ + - ]: 96434 : Stubs::iterator i(stubs_.find(oid));
518 [ + + ]: 96434 : if (i == stubs_.end()) {
519 : : throw css::uno::RuntimeException(
520 : : OUString(
521 : : RTL_CONSTASCII_USTRINGPARAM("URP: release unknown stub")),
522 [ + - ][ + - ]: 110 : css::uno::Reference< css::uno::XInterface >());
523 : : }
524 [ + - ]: 96324 : Stub::iterator j(i->second.find(type));
525 [ - + ]: 96324 : if (j == i->second.end()) {
526 : : throw css::uno::RuntimeException(
527 : : OUString(
528 : : RTL_CONSTASCII_USTRINGPARAM("URP: release unknown stub")),
529 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
530 : : }
531 : : assert(j->second.references > 0);
532 : 96324 : --j->second.references;
533 [ + + ]: 96324 : if (j->second.references == 0) {
534 [ + - ]: 53327 : obj = j->second.object;
535 [ + - ]: 53327 : i->second.erase(j);
536 [ + + ]: 53327 : if (i->second.empty()) {
537 [ + - ]: 35926 : stubs_.erase(i);
538 : : }
539 : : }
540 [ + - ]: 96434 : unused = becameUnused();
541 : : }
542 [ + + ]: 96324 : if (obj.is()) {
543 : 53327 : binaryUno_.get()->pExtEnv->revokeInterface(
544 [ + - ]: 53327 : binaryUno_.get()->pExtEnv, obj.get());
545 : : }
546 [ + - ][ + - ]: 96434 : terminateWhenUnused(unused);
547 : 96324 : }
548 : :
549 : 0 : void Bridge::resurrectProxy(Proxy & proxy) {
550 : 0 : uno_Interface * p = &proxy;
551 : 0 : binaryUno_.get()->pExtEnv->registerProxyInterface(
552 : 0 : binaryUno_.get()->pExtEnv,
553 : : reinterpret_cast< void ** >(&p), &freeProxyCallback,
554 : : proxy.getOid().pData,
555 : : reinterpret_cast< typelib_InterfaceTypeDescription * >(
556 [ # # # # ]: 0 : proxy.getType().get()));
[ # # ]
557 : : assert(p == &proxy);
558 : 0 : }
559 : :
560 : 3800 : void Bridge::revokeProxy(Proxy & proxy) {
561 : 3800 : binaryUno_.get()->pExtEnv->revokeInterface(
562 : 3800 : binaryUno_.get()->pExtEnv, &proxy);
563 : 3800 : }
564 : :
565 : 3800 : void Bridge::freeProxy(Proxy & proxy) {
566 : : try {
567 [ + - ][ + - ]: 3800 : makeReleaseCall(proxy.getOid(), proxy.getType());
[ + + ]
[ - + - ]
568 : 57 : } catch (const css::uno::RuntimeException & e) {
569 : : SAL_INFO(
570 : : "binaryurp", "caught runtime exception '" << e.Message << '\'');
571 : 0 : } catch (const std::exception & e) {
572 : : SAL_WARN("binaryurp", "caught C++ exception '" << e.what() << '\'');
573 : : }
574 : : bool unused;
575 : : {
576 [ + - ]: 3800 : osl::MutexGuard g(mutex_);
577 : : assert(proxies_ > 0);
578 : 3800 : --proxies_;
579 [ + - ]: 3800 : unused = becameUnused();
580 : : }
581 : 3800 : terminateWhenUnused(unused);
582 : 3800 : }
583 : :
584 : 477069 : void Bridge::incrementCalls(bool normalCall) throw () {
585 [ + - ]: 477069 : osl::MutexGuard g(mutex_);
586 : : assert(calls_ < std::numeric_limits< std::size_t >::max());
587 : 477069 : ++calls_;
588 [ + - ]: 477069 : normalCall_ |= normalCall;
589 : 477069 : }
590 : :
591 : 477058 : void Bridge::decrementCalls() {
592 : : bool unused;
593 : : {
594 [ + - ]: 477058 : osl::MutexGuard g(mutex_);
595 : : assert(calls_ > 0);
596 : 477062 : --calls_;
597 [ + - ]: 477062 : unused = becameUnused();
598 : : }
599 : 477062 : terminateWhenUnused(unused);
600 : 477062 : }
601 : :
602 : 380329 : void Bridge::incrementActiveCalls() throw () {
603 [ + - ]: 380329 : osl::MutexGuard g(mutex_);
604 : : assert(
605 : : activeCalls_ <= calls_ &&
606 : : activeCalls_ < std::numeric_limits< std::size_t >::max());
607 : 380329 : ++activeCalls_;
608 [ + - ][ + - ]: 380329 : passive_.reset();
609 : 380329 : }
610 : :
611 : 380329 : void Bridge::decrementActiveCalls() throw () {
612 [ + - ]: 380329 : osl::MutexGuard g(mutex_);
613 : : assert(activeCalls_ <= calls_ && activeCalls_ > 0);
614 : 380329 : --activeCalls_;
615 [ + + ]: 380329 : if (activeCalls_ == 0) {
616 [ + - ]: 358659 : passive_.set();
617 [ + - ]: 380329 : }
618 : 380329 : }
619 : :
620 : 13608 : bool Bridge::makeCall(
621 : : OUString const & oid, css::uno::TypeDescription const & member,
622 : : bool setter, std::vector< BinaryAny > const & inArguments,
623 : : BinaryAny * returnValue, std::vector< BinaryAny > * outArguments)
624 : : {
625 : 13608 : std::auto_ptr< IncomingReply > resp;
626 : : {
627 [ + + ]: 13608 : uno_ThreadPool tp = getThreadPool();
628 : 13606 : AttachThread att(tp);
629 : : PopOutgoingRequest pop(
630 : : outgoingRequests_, att.getTid(),
631 [ + - ]: 13606 : OutgoingRequest(OutgoingRequest::KIND_NORMAL, member, setter));
632 : : sendRequest(
633 : : att.getTid(), oid, css::uno::TypeDescription(), member,
634 [ + - ]: 13606 : inArguments);
635 : 13606 : pop.clear();
636 : 13606 : incrementCalls(true);
637 : 13606 : incrementActiveCalls();
638 : : void * job;
639 : 13606 : uno_threadpool_enter(tp, &job);
640 : 13606 : resp.reset(static_cast< IncomingReply * >(job));
641 : 13606 : decrementActiveCalls();
642 [ + - ]: 13608 : decrementCalls();
643 : : }
644 [ - + ]: 13606 : if (resp.get() == 0) {
645 : : throw css::lang::DisposedException(
646 : : OUString(
647 : : RTL_CONSTASCII_USTRINGPARAM(
648 : : "Binary URP bridge disposed during call")),
649 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
[ # # ]
650 : : }
651 : 13606 : *returnValue = resp->returnValue;
652 [ + + ]: 13606 : if (!resp->exception) {
653 [ + - ]: 13574 : *outArguments = resp->outArguments;
654 : : }
655 : 13608 : return resp->exception;
656 : : }
657 : :
658 : 102 : void Bridge::sendRequestChangeRequest() {
659 : : assert(mode_ == MODE_REQUESTED);
660 : 102 : random_ = random();
661 [ + - ]: 102 : std::vector< BinaryAny > a;
662 : : a.push_back(
663 : : BinaryAny(
664 : 102 : css::uno::TypeDescription(cppu::UnoType< sal_Int32 >::get()),
665 [ + - ]: 102 : &random_));
666 [ + - ]: 102 : sendProtPropRequest(OutgoingRequest::KIND_REQUEST_CHANGE, a);
667 : 102 : }
668 : :
669 : 102 : void Bridge::handleRequestChangeReply(
670 : : bool exception, BinaryAny const & returnValue)
671 : : {
672 : : try {
673 [ + - ]: 102 : throwException(exception, returnValue);
674 [ # # ]: 0 : } catch (css::uno::RuntimeException & e) {
675 : : // Before OOo 2.2, Java URP would throw a RuntimeException when
676 : : // receiving a requestChange message (see i#35277 "Java URP: Support
677 : : // Manipulation of Protocol Properties"):
678 [ # # ]: 0 : if (mode_ != MODE_REQUESTED) {
679 : 0 : throw;
680 : : }
681 : : SAL_WARN(
682 : : "binaryurp",
683 : : "requestChange caught RuntimeException \'" << e.Message
684 : : << "' in state 'requested'");
685 : 0 : mode_ = MODE_NORMAL;
686 [ # # # # : 0 : getWriter()->unblock();
# # ]
687 [ # # ]: 0 : decrementCalls();
688 : 102 : return;
689 : : }
690 : : sal_Int32 n = *static_cast< sal_Int32 * >(
691 : : returnValue.getValue(
692 : 102 : css::uno::TypeDescription(cppu::UnoType< sal_Int32 >::get())));
693 : 102 : sal_Int32 exp = 0;
694 [ + - + - ]: 102 : switch (mode_) {
695 : : case MODE_REQUESTED:
696 : : case MODE_REPLY_1:
697 : 59 : exp = 1;
698 : 59 : break;
699 : : case MODE_REPLY_MINUS1:
700 : 0 : exp = -1;
701 : 0 : mode_ = MODE_REQUESTED;
702 : 0 : break;
703 : : case MODE_REPLY_0:
704 : 43 : exp = 0;
705 : 43 : mode_ = MODE_WAIT;
706 : 43 : break;
707 : : default:
708 : : assert(false); // this cannot happen
709 : 0 : break;
710 : : }
711 [ - + ]: 102 : if (n != exp) {
712 : : throw css::uno::RuntimeException(
713 : : OUString(
714 : : RTL_CONSTASCII_USTRINGPARAM(
715 : : "URP: requestChange reply with unexpected return value"
716 : : " received")),
717 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
[ # # ]
718 : : }
719 : 102 : decrementCalls();
720 [ - + + - ]: 102 : switch (exp) {
721 : : case -1:
722 : 0 : sendRequestChangeRequest();
723 : 0 : break;
724 : : case 0:
725 : 43 : break;
726 : : case 1:
727 : 59 : sendCommitChangeRequest();
728 : 59 : break;
729 : : default:
730 : : assert(false); // this cannot happen
731 : 0 : break;
732 : : }
733 : : }
734 : :
735 : 59 : void Bridge::handleCommitChangeReply(
736 : : bool exception, BinaryAny const & returnValue)
737 : : {
738 : 59 : bool ccMode = true;
739 : : try {
740 [ + - ]: 59 : throwException(exception, returnValue);
741 : 0 : } catch (const css::bridge::InvalidProtocolChangeException &) {
742 : 0 : ccMode = false;
743 : : }
744 [ + - ]: 59 : if (ccMode) {
745 : 59 : setCurrentContextMode();
746 : : }
747 : : assert(mode_ == MODE_REQUESTED || mode_ == MODE_REPLY_1);
748 : 59 : mode_ = MODE_NORMAL;
749 [ + - ]: 59 : getWriter()->unblock();
750 : 59 : decrementCalls();
751 [ # # ]: 59 : }
752 : :
753 : 102 : void Bridge::handleRequestChangeRequest(
754 : : rtl::ByteSequence const & tid, std::vector< BinaryAny > const & inArguments)
755 : : {
756 : : assert(inArguments.size() == 1);
757 [ + - - ]: 102 : switch (mode_) {
758 : : case MODE_REQUESTED:
759 : : {
760 : : sal_Int32 n2 = *static_cast< sal_Int32 * >(
761 : 102 : inArguments[0].getValue(
762 : : css::uno::TypeDescription(
763 : 204 : cppu::UnoType< sal_Int32 >::get())));
764 : : sal_Int32 ret;
765 [ + + ]: 102 : if (n2 > random_) {
766 : 43 : ret = 1;
767 : 43 : mode_ = MODE_REPLY_0;
768 [ - + ]: 59 : } else if (n2 == random_) {
769 : 0 : ret = -1;
770 : 0 : mode_ = MODE_REPLY_MINUS1;
771 : : } else {
772 : 59 : ret = 0;
773 : 59 : mode_ = MODE_REPLY_1;
774 : : }
775 : : getWriter()->sendDirectReply(
776 : : tid, protPropRequest_, false,
777 : : BinaryAny(
778 : : css::uno::TypeDescription(
779 : 102 : cppu::UnoType< sal_Int32 >::get()),
780 : : &ret),
781 [ + - + - ]: 204 : std::vector< BinaryAny >());
[ + - ][ + - ]
782 : : break;
783 : : }
784 : : case MODE_NORMAL:
785 : : {
786 : 0 : mode_ = MODE_NORMAL_WAIT;
787 : 0 : sal_Int32 ret = 1;
788 : : getWriter()->queueReply(
789 : : tid, protPropRequest_, false, false,
790 : : BinaryAny(
791 : : css::uno::TypeDescription(
792 : 0 : cppu::UnoType< sal_Int32 >::get()),
793 : : &ret),
794 [ # # # # ]: 0 : std::vector< BinaryAny >(), false);
[ # # ][ # # ]
795 : : break;
796 : : }
797 : : default:
798 : : throw css::uno::RuntimeException(
799 : : OUString(
800 : : RTL_CONSTASCII_USTRINGPARAM(
801 : : "URP: unexpected requestChange request received")),
802 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
[ # # ]
803 : : }
804 : 102 : }
805 : :
806 : 43 : void Bridge::handleCommitChangeRequest(
807 : : rtl::ByteSequence const & tid, std::vector< BinaryAny > const & inArguments)
808 : : {
809 : 43 : bool ccMode = false;
810 : 43 : bool exc = false;
811 : 43 : BinaryAny ret;
812 : : assert(inArguments.size() == 1);
813 [ + - ]: 43 : css::uno::Sequence< css::bridge::ProtocolProperty > s;
814 [ + - ][ + - ]: 43 : bool ok = (mapBinaryToCppAny(inArguments[0]) >>= s);
815 : : assert(ok);
816 : : (void) ok; // avoid warnings
817 [ + + ]: 86 : for (sal_Int32 i = 0; i != s.getLength(); ++i) {
818 [ + - ][ + - ]: 43 : if ( s[i].Name == "CurrentContext" )
819 : : {
820 : 43 : ccMode = true;
821 : : } else {
822 : 0 : ccMode = false;
823 : 0 : exc = true;
824 : : ret = mapCppToBinaryAny(
825 : : css::uno::makeAny(
826 : : css::bridge::InvalidProtocolChangeException(
827 : : OUString(
828 : : RTL_CONSTASCII_USTRINGPARAM(
829 : : "InvalidProtocolChangeException")),
830 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface >(), s[i],
831 [ # # ][ # # ]: 0 : 1)));
[ # # ][ # # ]
[ # # ]
832 : 0 : break;
833 : : }
834 : : }
835 [ + - - ]: 43 : switch (mode_) {
836 : : case MODE_WAIT:
837 : : getWriter()->sendDirectReply(
838 [ + - ][ + - ]: 43 : tid, protPropCommit_, exc, ret, std::vector< BinaryAny >());
[ + - ][ + - ]
839 [ + - ]: 43 : if (ccMode) {
840 [ + - ]: 43 : setCurrentContextMode();
841 : 43 : mode_ = MODE_NORMAL;
842 [ + - ][ + - ]: 43 : getWriter()->unblock();
[ + - ]
843 : : } else {
844 : 0 : mode_ = MODE_REQUESTED;
845 [ # # ]: 0 : sendRequestChangeRequest();
846 : : }
847 : 43 : break;
848 : : case MODE_NORMAL_WAIT:
849 : : getWriter()->queueReply(
850 : : tid, protPropCommit_, false, false, ret, std::vector< BinaryAny >(),
851 [ # # ][ # # ]: 0 : ccMode);
[ # # ][ # # ]
852 : 0 : mode_ = MODE_NORMAL;
853 : 0 : break;
854 : : default:
855 : : throw css::uno::RuntimeException(
856 : : OUString(
857 : : RTL_CONSTASCII_USTRINGPARAM(
858 : : "URP: unexpected commitChange request received")),
859 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
[ # # ]
860 [ + - ]: 43 : }
861 : 43 : }
862 : :
863 : 13767 : OutgoingRequest Bridge::lastOutgoingRequest(rtl::ByteSequence const & tid) {
864 : 13767 : OutgoingRequest req(outgoingRequests_.top(tid));
865 : 13767 : outgoingRequests_.pop(tid);
866 : 13767 : return req;
867 : : }
868 : :
869 : 463302 : bool Bridge::isProtocolPropertiesRequest(
870 : : OUString const & oid, css::uno::TypeDescription const & type) const
871 : : {
872 [ + + ][ + - ]: 463302 : return oid == protPropOid_ && type.equals(protPropType_);
873 : : }
874 : :
875 : 102 : void Bridge::setCurrentContextMode() {
876 [ + - ]: 102 : osl::MutexGuard g(mutex_);
877 [ + - ]: 102 : currentContextMode_ = true;
878 : 102 : }
879 : :
880 : 380329 : bool Bridge::isCurrentContextMode() {
881 [ + - ]: 380329 : osl::MutexGuard g(mutex_);
882 [ + - ]: 380329 : return currentContextMode_;
883 : : }
884 : :
885 [ + - ][ + - ]: 96 : Bridge::~Bridge() {
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
886 : : #if OSL_DEBUG_LEVEL > 0
887 : : {
888 : : osl::MutexGuard g(mutex_);
889 : : SAL_WARN_IF(
890 : : state_ == STATE_STARTED || state_ == STATE_TERMINATED, "binaryurp",
891 : : "undisposed bridge, potential deadlock ahead");
892 : : }
893 : : #endif
894 [ + - ]: 96 : dispose();
895 [ - + ]: 192 : }
896 : :
897 : 4 : css::uno::Reference< css::uno::XInterface > Bridge::getInstance(
898 : : OUString const & sInstanceName) throw (css::uno::RuntimeException)
899 : : {
900 [ - + ]: 4 : if (sInstanceName.isEmpty()) {
901 : : throw css::uno::RuntimeException(
902 : : OUString(
903 : : RTL_CONSTASCII_USTRINGPARAM(
904 : : "XBridge::getInstance sInstanceName must be non-empty")),
905 [ # # ][ # # ]: 0 : static_cast< cppu::OWeakObject * >(this));
[ # # ]
906 : : }
907 [ + + ]: 98 : for (sal_Int32 i = 0; i != sInstanceName.getLength(); ++i) {
908 [ - + ]: 94 : if (sInstanceName[i] > 0x7F) {
909 : : throw css::io::IOException(
910 : : OUString(
911 : : RTL_CONSTASCII_USTRINGPARAM(
912 : : "XBridge::getInstance sInstanceName contains non-ASCII"
913 : : " character")),
914 [ # # ][ # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
915 : : }
916 : : }
917 : : css::uno::TypeDescription ifc(
918 [ + - ]: 4 : cppu::UnoType< css::uno::Reference< css::uno::XInterface > >::get());
919 : 4 : typelib_TypeDescription * p = ifc.get();
920 [ + - ]: 4 : std::vector< BinaryAny > inArgs;
921 : : inArgs.push_back(
922 : : BinaryAny(
923 : 4 : css::uno::TypeDescription(cppu::UnoType< css::uno::Type >::get()),
924 [ + - ]: 4 : &p));
925 : 4 : BinaryAny ret;
926 [ + - ]: 4 : std::vector< BinaryAny> outArgs;
927 : : bool exc = makeCall(
928 : : sInstanceName,
929 : : css::uno::TypeDescription(
930 : : OUString(
931 : : RTL_CONSTASCII_USTRINGPARAM(
932 : : "com.sun.star.uno.XInterface::queryInterface"))),
933 [ + - ][ + - ]: 4 : false, inArgs, &ret, &outArgs);
934 [ + - ]: 4 : throwException(exc, ret);
935 : : return css::uno::Reference< css::uno::XInterface >(
936 : : static_cast< css::uno::XInterface * >(
937 : : binaryToCppMapping_.mapInterface(
938 : 4 : *static_cast< uno_Interface ** >(ret.getValue(ifc)),
939 [ + - ]: 8 : ifc.get())),
940 [ + - ]: 4 : css::uno::UNO_REF_NO_ACQUIRE);
941 : : }
942 : :
943 : 100 : OUString Bridge::getName() throw (css::uno::RuntimeException) {
944 : 100 : return name_;
945 : : }
946 : :
947 : 0 : OUString Bridge::getDescription() throw (css::uno::RuntimeException) {
948 [ # # ]: 0 : OUStringBuffer b(name_);
949 [ # # ]: 0 : b.append(sal_Unicode(':'));
950 [ # # ][ # # ]: 0 : b.append(connection_->getDescription());
[ # # ]
951 [ # # ]: 0 : return b.makeStringAndClear();
952 : : }
953 : :
954 : 194 : void Bridge::dispose() throw (css::uno::RuntimeException) {
955 : : // For terminate(true) not to deadlock, an external protocol must ensure
956 : : // that dispose is not called from a thread pool worker thread (that dispose
957 : : // is never called from the reader or writer thread is already ensured
958 : : // internally):
959 : 194 : terminate(true);
960 : : // OOo expects dispose to not return while there are still remote calls in
961 : : // progress; an external protocol must ensure that dispose is not called
962 : : // from within an incoming or outgoing remote call, as passive_.wait() would
963 : : // otherwise deadlock:
964 : 194 : passive_.wait();
965 : 194 : }
966 : :
967 : 2 : void Bridge::addEventListener(
968 : : css::uno::Reference< css::lang::XEventListener > const & xListener)
969 : : throw (css::uno::RuntimeException)
970 : : {
971 : : assert(xListener.is());
972 : : {
973 [ + - ]: 2 : osl::MutexGuard g(mutex_);
974 : : assert(state_ != STATE_INITIAL);
975 [ + - ]: 2 : if (state_ == STATE_STARTED) {
976 [ + - ]: 2 : listeners_.push_back(xListener);
977 : 2 : return;
978 [ + - ][ - + ]: 2 : }
979 : : }
980 : 0 : xListener->disposing(
981 [ # # ][ # # ]: 2 : css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
[ # # ]
982 : : }
983 : :
984 : 0 : void Bridge::removeEventListener(
985 : : css::uno::Reference< css::lang::XEventListener > const & aListener)
986 : : throw (css::uno::RuntimeException)
987 : : {
988 [ # # ]: 0 : osl::MutexGuard g(mutex_);
989 : : Listeners::iterator i(
990 [ # # ]: 0 : std::find(listeners_.begin(), listeners_.end(), aListener));
991 [ # # ]: 0 : if (i != listeners_.end()) {
992 [ # # ]: 0 : listeners_.erase(i);
993 [ # # ]: 0 : }
994 : 0 : }
995 : :
996 : 59 : void Bridge::sendCommitChangeRequest() {
997 : : assert(mode_ == MODE_REQUESTED || mode_ == MODE_REPLY_1);
998 [ + - ]: 59 : css::uno::Sequence< css::bridge::ProtocolProperty > s(1);
999 [ + - ][ + - ]: 59 : s[0].Name = OUString(RTL_CONSTASCII_USTRINGPARAM("CurrentContext"));
1000 [ + - ]: 59 : std::vector< BinaryAny > a;
1001 [ + - ][ + - ]: 59 : a.push_back(mapCppToBinaryAny(css::uno::makeAny(s)));
[ + - ]
1002 [ + - ][ + - ]: 59 : sendProtPropRequest(OutgoingRequest::KIND_COMMIT_CHANGE, a);
1003 : 59 : }
1004 : :
1005 : 161 : void Bridge::sendProtPropRequest(
1006 : : OutgoingRequest::Kind kind, std::vector< BinaryAny > const & inArguments)
1007 : : {
1008 : : assert(
1009 : : kind == OutgoingRequest::KIND_REQUEST_CHANGE ||
1010 : : kind == OutgoingRequest::KIND_COMMIT_CHANGE);
1011 : 161 : incrementCalls(false);
1012 : : css::uno::TypeDescription member(
1013 : : kind == OutgoingRequest::KIND_REQUEST_CHANGE
1014 [ + + ]: 161 : ? protPropRequest_ : protPropCommit_);
1015 : : PopOutgoingRequest pop(
1016 [ + - ]: 161 : outgoingRequests_, protPropTid_, OutgoingRequest(kind, member, false));
1017 : : getWriter()->sendDirectRequest(
1018 [ + - ][ + - ]: 161 : protPropTid_, protPropOid_, protPropType_, member, inArguments);
[ + - ]
1019 : 161 : pop.clear();
1020 : 161 : }
1021 : :
1022 : 9233 : void Bridge::makeReleaseCall(
1023 : : OUString const & oid, css::uno::TypeDescription const & type)
1024 : : {
1025 [ + + ]: 9233 : AttachThread att(getThreadPool());
1026 : : sendRequest(
1027 : : att.getTid(), oid, type,
1028 : : css::uno::TypeDescription(
1029 : : OUString(
1030 : : RTL_CONSTASCII_USTRINGPARAM(
1031 : : "com.sun.star.uno.XInterface::release"))),
1032 [ + - ][ + - ]: 9233 : std::vector< BinaryAny >());
[ + - ]
1033 : 9176 : }
1034 : :
1035 : 22782 : void Bridge::sendRequest(
1036 : : rtl::ByteSequence const & tid, OUString const & oid,
1037 : : css::uno::TypeDescription const & type,
1038 : : css::uno::TypeDescription const & member,
1039 : : std::vector< BinaryAny > const & inArguments)
1040 : : {
1041 [ + - ]: 22782 : getWriter()->queueRequest(tid, oid, type, member, inArguments);
1042 : 22782 : }
1043 : :
1044 : 165 : void Bridge::throwException(bool exception, BinaryAny const & value) {
1045 [ - + ]: 165 : if (exception) {
1046 [ # # ]: 0 : cppu::throwException(mapBinaryToCppAny(value));
1047 : : }
1048 : 165 : }
1049 : :
1050 : 43 : css::uno::Any Bridge::mapBinaryToCppAny(BinaryAny const & binaryAny) {
1051 : 43 : BinaryAny in(binaryAny);
1052 : 43 : css::uno::Any out;
1053 : 43 : out.~Any();
1054 : : uno_copyAndConvertData(
1055 : 43 : &out, in.get(),
1056 : 43 : css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).get(),
1057 : 129 : binaryToCppMapping_.get());
1058 : 43 : return out;
1059 : : }
1060 : :
1061 : 577186 : bool Bridge::becameUnused() const {
1062 [ + + ][ + + ]: 577186 : return stubs_.empty() && proxies_ == 0 && calls_ == 0 && normalCall_;
[ + + ][ + + ]
1063 : : }
1064 : :
1065 : 577185 : void Bridge::terminateWhenUnused(bool unused) {
1066 [ + + ]: 577185 : if (unused) {
1067 : : // That the current thread considers the bridge unused implies that it
1068 : : // is not within an incoming or outgoing remote call (so calling
1069 : : // terminate cannot lead to deadlock):
1070 : 19 : terminate(false);
1071 : : }
1072 : 577185 : }
1073 : :
1074 : 889517 : void Bridge::checkDisposed() {
1075 : : assert(state_ != STATE_INITIAL);
1076 [ + + ]: 889517 : if (state_ != STATE_STARTED) {
1077 : : throw css::lang::DisposedException(
1078 : : OUString(
1079 : : RTL_CONSTASCII_USTRINGPARAM(
1080 : : "Binary URP bridge already disposed")),
1081 [ + - ][ + - ]: 65 : static_cast< cppu::OWeakObject * >(this));
[ + - ]
1082 : : }
1083 : 889452 : }
1084 : :
1085 : : }
1086 : :
1087 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|