LCOV - code coverage report
Current view: top level - binaryurp/source - bridge.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 410 479 85.6 %
Date: 2012-08-25 Functions: 56 60 93.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 337 721 46.7 %

           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: */

Generated by: LCOV version 1.10