/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



#include "sal/config.h"

#include <algorithm>
#include <cstddef>
#include <limits>
#include <memory>
#include <vector>

#include "boost/noncopyable.hpp"
#include "com/sun/star/bridge/InvalidProtocolChangeException.hpp"
#include "com/sun/star/bridge/XBridge.hpp"
#include "com/sun/star/bridge/XInstanceProvider.hpp"
#include "com/sun/star/bridge/XProtocolProperties.hpp"
#include "com/sun/star/connection/XConnection.hpp"
#include "com/sun/star/io/IOException.hpp"
#include "com/sun/star/lang/DisposedException.hpp"
#include "com/sun/star/lang/EventObject.hpp"
#include "com/sun/star/lang/XEventListener.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/XInterface.hpp"
#include "cppuhelper/exc_hlp.hxx"
#include "cppuhelper/weak.hxx"
#include "osl/diagnose.h"
#include "osl/mutex.hxx"
#include "osl/thread.hxx"
#include "rtl/byteseq.hxx"
#include "rtl/random.h"
#include "rtl/ref.hxx"
#include "rtl/textenc.h"
#include "rtl/ustrbuf.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "typelib/typeclass.h"
#include "typelib/typedescription.h"
#include "typelib/typedescription.hxx"
#include "uno/dispatcher.hxx"
#include "uno/environment.hxx"
#include "uno/lbnames.h"

#include "binaryany.hxx"
#include "bridge.hxx"
#include "bridgefactory.hxx"
#include "incomingreply.hxx"
#include "lessoperators.hxx"
#include "outgoingrequest.hxx"
#include "outgoingrequests.hxx"
#include "proxy.hxx"
#include "reader.hxx"

namespace binaryurp {

namespace {

namespace css = com::sun::star;

sal_Int32 random() {
    sal_Int32 n;
    rtlRandomPool pool = rtl_random_createPool();
    rtl_random_getBytes(pool, &n, sizeof n);
    rtl_random_destroyPool(pool);
    return n;
}

extern "C" void SAL_CALL freeProxyCallback(uno_ExtEnvironment *, void * pProxy)
{
    OSL_ASSERT(pProxy != 0);
    static_cast< Proxy * >(pProxy)->do_free();
}

void joinThread(osl::Thread * thread) {
    OSL_ASSERT(thread != 0);
    if (thread->getIdentifier() != osl::Thread::getCurrentIdentifier()) {
        thread->join();
    }
}

class AttachThread: private boost::noncopyable {
public:
    explicit AttachThread(uno_ThreadPool threadPool);

    ~AttachThread();

    rtl::ByteSequence getTid() throw ();

private:
    uno_ThreadPool threadPool_;
    rtl::ByteSequence tid_;
};

AttachThread::AttachThread(uno_ThreadPool threadPool): threadPool_(threadPool) {
    sal_Sequence * s = 0;
    uno_getIdOfCurrentThread(&s);
    tid_ = rtl::ByteSequence(s, rtl::BYTESEQ_NOACQUIRE);
    uno_threadpool_attach(threadPool_);
}

AttachThread::~AttachThread() {
    uno_threadpool_detach(threadPool_);
    uno_releaseIdFromCurrentThread();
}

rtl::ByteSequence AttachThread::getTid() throw () {
    return tid_;
}

class PopOutgoingRequest: private boost::noncopyable {
public:
    PopOutgoingRequest(
        OutgoingRequests & requests, rtl::ByteSequence const & tid,
        OutgoingRequest const & request);

    ~PopOutgoingRequest();

    void clear();

private:
    OutgoingRequests & requests_;
    rtl::ByteSequence tid_;
    bool cleared_;
};

PopOutgoingRequest::PopOutgoingRequest(
    OutgoingRequests & requests, rtl::ByteSequence const & tid,
    OutgoingRequest const & request):
    requests_(requests), tid_(tid), cleared_(false)
{
    requests_.push(tid_, request);
}

PopOutgoingRequest::~PopOutgoingRequest() {
    if (!cleared_) {
        requests_.pop(tid_);
    }
}

void PopOutgoingRequest::clear() {
    cleared_ = true;
}

}

Bridge::Bridge(
    rtl::Reference< BridgeFactory > const & factory, rtl::OUString const & name,
    css::uno::Reference< css::connection::XConnection > const & connection,
    css::uno::Reference< css::bridge::XInstanceProvider > const & provider):
    factory_(factory), name_(name), connection_(connection),
    provider_(provider),
    binaryUno_(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO))),
    cppToBinaryMapping_(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME)),
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO))),
    binaryToCppMapping_(
        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO)),
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME))),
    protPropTid_(
        reinterpret_cast< sal_Int8 const * >(".UrpProtocolPropertiesTid"),
        RTL_CONSTASCII_LENGTH(".UrpProtocolPropertiesTid")),
    protPropOid_(RTL_CONSTASCII_USTRINGPARAM("UrpProtocolProperties")),
    protPropType_(
        cppu::UnoType<
            css::uno::Reference< css::bridge::XProtocolProperties > >::get()),
    protPropRequest_(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "com.sun.star.bridge.XProtocolProperties::requestChange"))),
    protPropCommit_(
        rtl::OUString(
            RTL_CONSTASCII_USTRINGPARAM(
                "com.sun.star.bridge.XProtocolProperties::commitChange"))),
    threadPool_(0), currentContextMode_(false), proxies_(0), calls_(0),
    normalCall_(false), activeCalls_(0), terminated_(false),
    mode_(MODE_REQUESTED)
{
    OSL_ASSERT(factory.is() && connection.is());
    if (!binaryUno_.is()) {
        throw css::uno::RuntimeException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM("URP: no binary UNO environment")),
            css::uno::Reference< css::uno::XInterface >());
    }
    if (!(cppToBinaryMapping_.is() && binaryToCppMapping_.is())) {
        throw css::uno::RuntimeException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM("URP: no C++ UNO mapping")),
            css::uno::Reference< css::uno::XInterface >());
    }
    passive_.set();
}

void Bridge::start() {
    OSL_ASSERT(threadPool_ == 0 && !writer_.is() && !reader_.is());
    threadPool_ = uno_threadpool_create();
    OSL_ASSERT(threadPool_ != 0);
    writer_.set(new Writer(this));
    writer_->create();
    reader_.set(new Reader(this));
    reader_->create();
}

void Bridge::terminate() {
    rtl::Reference< Reader > r;
    rtl::Reference< Writer > w;
    Listeners ls;
    {
        osl::MutexGuard g(mutex_);
        if (terminated_) {
            return;
        }
        std::swap(reader_, r);
        std::swap(writer_, w);
        ls.swap(listeners_);
        terminated_ = true;
    }
    try {
        connection_->close();
    } catch (css::io::IOException & e) {
        OSL_TRACE(
            OSL_LOG_PREFIX "caught IO exception '%s'",
            rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
    }
    OSL_ASSERT(w.is());
    w->stop();
    joinThread(r.get());
    joinThread(w.get());
    OSL_ASSERT(threadPool_ != 0);
    uno_threadpool_dispose(threadPool_);
    Stubs s;
    {
        osl::MutexGuard g(mutex_);
        s.swap(stubs_);
    }
    for (Stubs::iterator i(s.begin()); i != s.end(); ++i) {
        for (Stub::iterator j(i->second.begin()); j != i->second.end(); ++j) {
            binaryUno_.get()->pExtEnv->revokeInterface(
                binaryUno_.get()->pExtEnv, j->second.object.get());
        }
    }
    factory_->removeBridge(this);
    for (Listeners::iterator i(ls.begin()); i != ls.end(); ++i) {
        try {
            (*i)->disposing(
                css::lang::EventObject(
                    static_cast< cppu::OWeakObject * >(this)));
        } catch (css::uno::RuntimeException & e) {
            OSL_TRACE(
                OSL_LOG_PREFIX "caught runtime exception '%s'",
                rtl::OUStringToOString(
                    e.Message, RTL_TEXTENCODING_UTF8).getStr());
        }
    }
}

css::uno::Reference< css::connection::XConnection > Bridge::getConnection()
    const
{
    return connection_;
}

css::uno::Reference< css::bridge::XInstanceProvider > Bridge::getProvider()
    const
{
    return provider_;
}

css::uno::Mapping & Bridge::getCppToBinaryMapping() {
    return cppToBinaryMapping_;
}

BinaryAny Bridge::mapCppToBinaryAny(css::uno::Any const & cppAny) {
    css::uno::Any in(cppAny);
    BinaryAny out;
    out.~BinaryAny();
    uno_copyAndConvertData(
        out.get(), &in,
        css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).get(),
        cppToBinaryMapping_.get());
    return out;
}

uno_ThreadPool Bridge::getThreadPool() const {
    OSL_ASSERT(threadPool_ != 0);
    return threadPool_;
}

rtl::Reference< Writer > Bridge::getWriter() {
    osl::MutexGuard g(mutex_);
    if (terminated_) {
        throw css::lang::DisposedException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "Binary URP bridge already disposed")),
            static_cast< cppu::OWeakObject * >(this));
    }
    OSL_ASSERT(writer_.is());
    return writer_;
}

css::uno::UnoInterfaceReference Bridge::registerIncomingInterface(
    rtl::OUString const & oid, css::uno::TypeDescription const & type)
{
    OSL_ASSERT(type.is());
    if ( oid.isEmpty() ) {
        return css::uno::UnoInterfaceReference();
    }
    css::uno::UnoInterfaceReference obj(findStub(oid, type));
    if (!obj.is()) {
        binaryUno_.get()->pExtEnv->getRegisteredInterface(
            binaryUno_.get()->pExtEnv,
            reinterpret_cast< void ** >(&obj.m_pUnoI), oid.pData,
            reinterpret_cast< typelib_InterfaceTypeDescription * >(type.get()));
        if (obj.is()) {
            makeReleaseCall(oid, type);
        } else {
            obj.set(new Proxy(this, oid, type), SAL_NO_ACQUIRE);
            {
                osl::MutexGuard g(mutex_);
                OSL_ASSERT(
                    proxies_ < std::numeric_limits< std::size_t >::max());
                ++proxies_;
            }
            binaryUno_.get()->pExtEnv->registerProxyInterface(
                binaryUno_.get()->pExtEnv,
                reinterpret_cast< void ** >(&obj.m_pUnoI), &freeProxyCallback,
                oid.pData,
                reinterpret_cast< typelib_InterfaceTypeDescription * >(
                    type.get()));
        }
    }
    return obj;
}

rtl::OUString Bridge::registerOutgoingInterface(
    css::uno::UnoInterfaceReference const & object,
    css::uno::TypeDescription const & type)
{
    OSL_ASSERT(type.is());
    if (!object.is()) {
        return rtl::OUString();
    }
    rtl::OUString oid;
    if (!Proxy::isProxy(this, object, &oid)) {
        binaryUno_.get()->pExtEnv->getObjectIdentifier(
            binaryUno_.get()->pExtEnv, &oid.pData, object.get());
        osl::MutexGuard g(mutex_);
        Stubs::iterator i(stubs_.find(oid));
        Stub newStub;
        Stub * stub = i == stubs_.end() ? &newStub : &i->second;
        Stub::iterator j(stub->find(type));
        //TODO: Release sub-stub if it is not successfully sent to remote side
        // (otherwise, stub will leak until terminate()):
        if (j == stub->end()) {
            j = stub->insert(Stub::value_type(type, SubStub())).first;
            if (stub == &newStub) {
                i = stubs_.insert(Stubs::value_type(oid, Stub())).first;
                std::swap(i->second, newStub);
                j = i->second.find(type);
                OSL_ASSERT(j !=  i->second.end());
            }
            j->second.object = object;
            j->second.references = 1;
            binaryUno_.get()->pExtEnv->registerInterface(
                binaryUno_.get()->pExtEnv,
                reinterpret_cast< void ** >(&j->second.object.m_pUnoI),
                oid.pData,
                reinterpret_cast< typelib_InterfaceTypeDescription * >(
                    type.get()));
        } else {
            OSL_ASSERT(stub != &newStub);
            if (j->second.references == SAL_MAX_UINT32) {
                throw css::uno::RuntimeException(
                    rtl::OUString(
                        RTL_CONSTASCII_USTRINGPARAM(
                            "URP: stub reference count overflow")),
                    css::uno::Reference< css::uno::XInterface >());
            }
            ++j->second.references;
        }
    }
    return oid;
}

css::uno::UnoInterfaceReference Bridge::findStub(
    rtl::OUString const & oid, css::uno::TypeDescription const & type)
{
    OSL_ASSERT(!oid.isEmpty() && type.is());
    osl::MutexGuard g(mutex_);
    Stubs::iterator i(stubs_.find(oid));
    if (i != stubs_.end()) {
        Stub::iterator j(i->second.find(type));
        if (j != i->second.end()) {
            return j->second.object;
        }
        for (j = i->second.begin(); j != i->second.end(); ++j) {
            if (typelib_typedescription_isAssignableFrom(
                    type.get(), j->first.get()))
            {
                return j->second.object;
            }
        }
    }
    return css::uno::UnoInterfaceReference();
}

void Bridge::releaseStub(
    rtl::OUString const & oid, css::uno::TypeDescription const & type)
{
    OSL_ASSERT(!oid.isEmpty() && type.is());
    css::uno::UnoInterfaceReference obj;
    bool unused;
    {
        osl::MutexGuard g(mutex_);
        Stubs::iterator i(stubs_.find(oid));
        if (i == stubs_.end()) {
            throw css::uno::RuntimeException(
                rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("URP: release unknown stub")),
                css::uno::Reference< css::uno::XInterface >());
        }
        Stub::iterator j(i->second.find(type));
        if (j == i->second.end()) {
            throw css::uno::RuntimeException(
                rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM("URP: release unknown stub")),
                css::uno::Reference< css::uno::XInterface >());
        }
        OSL_ASSERT(j->second.references > 0);
        --j->second.references;
        if (j->second.references == 0) {
            obj = j->second.object;
            i->second.erase(j);
            if (i->second.empty()) {
                stubs_.erase(i);
            }
        }
        unused = becameUnused();
    }
    if (obj.is()) {
        binaryUno_.get()->pExtEnv->revokeInterface(
            binaryUno_.get()->pExtEnv, obj.get());
    }
    terminateWhenUnused(unused);
}

void Bridge::resurrectProxy(Proxy & proxy) {
    uno_Interface * p = &proxy;
    binaryUno_.get()->pExtEnv->registerProxyInterface(
        binaryUno_.get()->pExtEnv,
        reinterpret_cast< void ** >(&p), &freeProxyCallback,
        proxy.getOid().pData,
        reinterpret_cast< typelib_InterfaceTypeDescription * >(
            proxy.getType().get()));
    OSL_ASSERT(p == &proxy);
}

void Bridge::revokeProxy(Proxy & proxy) {
    binaryUno_.get()->pExtEnv->revokeInterface(
        binaryUno_.get()->pExtEnv, &proxy);
}

void Bridge::freeProxy(Proxy & proxy) {
    try {
        makeReleaseCall(proxy.getOid(), proxy.getType());
    } catch (css::uno::RuntimeException & e) {
        OSL_TRACE(
            OSL_LOG_PREFIX "caught runtime exception '%s'",
            rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
    } catch (std::exception & e) {
        OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
    }
    bool unused;
    {
        osl::MutexGuard g(mutex_);
        OSL_ASSERT(proxies_ > 0);
        --proxies_;
        unused = becameUnused();
    }
    terminateWhenUnused(unused);
}

void Bridge::incrementCalls(bool normalCall) throw () {
    osl::MutexGuard g(mutex_);
    OSL_ASSERT(calls_ < std::numeric_limits< std::size_t >::max());
    ++calls_;
    normalCall_ |= normalCall;
}

void Bridge::decrementCalls() {
    bool unused;
    {
        osl::MutexGuard g(mutex_);
        OSL_ASSERT(calls_ > 0);
        --calls_;
        unused = becameUnused();
    }
    terminateWhenUnused(unused);
}

void Bridge::incrementActiveCalls() throw () {
    osl::MutexGuard g(mutex_);
    OSL_ASSERT(
        activeCalls_ <= calls_ &&
        activeCalls_ < std::numeric_limits< std::size_t >::max());
    ++activeCalls_;
    passive_.reset();
}

void Bridge::decrementActiveCalls() throw () {
    osl::MutexGuard g(mutex_);
    OSL_ASSERT(activeCalls_ <= calls_ && activeCalls_ > 0);
    --activeCalls_;
    if (activeCalls_ == 0) {
        passive_.set();
    }
}

bool Bridge::makeCall(
    rtl::OUString const & oid, css::uno::TypeDescription const & member,
    bool setter, std::vector< BinaryAny > const & inArguments,
    BinaryAny * returnValue, std::vector< BinaryAny > * outArguments)
{
    std::auto_ptr< IncomingReply > resp;
    {
        AttachThread att(threadPool_);
        PopOutgoingRequest pop(
            outgoingRequests_, att.getTid(),
            OutgoingRequest(OutgoingRequest::KIND_NORMAL, member, setter));
        sendRequest(
            att.getTid(), oid, css::uno::TypeDescription(), member,
            inArguments);
        pop.clear();
        incrementCalls(true);
        incrementActiveCalls();
        void * job;
        uno_threadpool_enter(threadPool_, &job);
        resp.reset(static_cast< IncomingReply * >(job));
        decrementActiveCalls();
        decrementCalls();
    }
    if (resp.get() == 0) {
        throw css::lang::DisposedException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "Binary URP bridge disposed during call")),
            static_cast< cppu::OWeakObject * >(this));
    }
    *returnValue = resp->returnValue;
    if (!resp->exception) {
        *outArguments = resp->outArguments;
    }
    return resp->exception;
}

void Bridge::sendRequestChangeRequest() {
    OSL_ASSERT(mode_ == MODE_REQUESTED);
    random_ = random();
    std::vector< BinaryAny > a;
    a.push_back(
        BinaryAny(
            css::uno::TypeDescription(cppu::UnoType< sal_Int32 >::get()),
            &random_));
    sendProtPropRequest(OutgoingRequest::KIND_REQUEST_CHANGE, a);
}

void Bridge::handleRequestChangeReply(
    bool exception, BinaryAny const & returnValue)
{
    throwException(exception, returnValue);
    sal_Int32 n = *static_cast< sal_Int32 * >(
        returnValue.getValue(
            css::uno::TypeDescription(cppu::UnoType< sal_Int32 >::get())));
    sal_Int32 exp = 0;
    switch (mode_) {
    case MODE_REQUESTED:
    case MODE_REPLY_1:
        exp = 1;
        break;
    case MODE_REPLY_MINUS1:
        exp = -1;
        mode_ = MODE_REQUESTED;
        break;
    case MODE_REPLY_0:
        exp = 0;
        mode_ = MODE_WAIT;
        break;
    default:
        OSL_ASSERT(false); // this cannot happen
        break;
    }
    if (n != exp) {
        throw css::uno::RuntimeException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "URP: requestChange reply with unexpected return value"
                    " received")),
            static_cast< cppu::OWeakObject * >(this));
    }
    decrementCalls();
    switch (exp) {
    case -1:
        sendRequestChangeRequest();
        break;
    case 0:
        break;
    case 1:
        sendCommitChangeRequest();
        break;
    default:
        OSL_ASSERT(false); // this cannot happen
        break;
    }
}

void Bridge::handleCommitChangeReply(
    bool exception, BinaryAny const & returnValue)
{
    bool ccMode = true;
    try {
        throwException(exception, returnValue);
    } catch (css::bridge::InvalidProtocolChangeException &) {
        ccMode = false;
    }
    if (ccMode) {
        setCurrentContextMode();
    }
    OSL_ASSERT(mode_ == MODE_REQUESTED || mode_ == MODE_REPLY_1);
    mode_ = MODE_NORMAL;
    getWriter()->unblock();
    decrementCalls();
}

void Bridge::handleRequestChangeRequest(
    rtl::ByteSequence const & tid, std::vector< BinaryAny > const & inArguments)
{
    OSL_ASSERT(inArguments.size() == 1);
    switch (mode_) {
    case MODE_REQUESTED:
        {
            sal_Int32 n2 = *static_cast< sal_Int32 * >(
                inArguments[0].getValue(
                    css::uno::TypeDescription(
                        cppu::UnoType< sal_Int32 >::get())));
            sal_Int32 ret;
            if (n2 > random_) {
                ret = 1;
                mode_ = MODE_REPLY_0;
            } else if (n2 == random_) {
                ret = -1;
                mode_ = MODE_REPLY_MINUS1;
            } else {
                ret = 0;
                mode_ = MODE_REPLY_1;
            }
            getWriter()->sendDirectReply(
                tid, protPropRequest_, false,
                BinaryAny(
                    css::uno::TypeDescription(
                        cppu::UnoType< sal_Int32 >::get()),
                    &ret),
            std::vector< BinaryAny >());
            break;
        }
    case MODE_NORMAL:
        {
            mode_ = MODE_NORMAL_WAIT;
            sal_Int32 ret = 1;
            getWriter()->queueReply(
                tid, protPropRequest_, false, false,
                BinaryAny(
                    css::uno::TypeDescription(
                        cppu::UnoType< sal_Int32 >::get()),
                    &ret),
            std::vector< BinaryAny >(), false);
            break;
        }
    default:
        throw css::uno::RuntimeException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "URP: unexpected requestChange request received")),
            static_cast< cppu::OWeakObject * >(this));
    }
}

void Bridge::handleCommitChangeRequest(
    rtl::ByteSequence const & tid, std::vector< BinaryAny > const & inArguments)
{
    bool ccMode = false;
    bool exc = false;
    BinaryAny ret;
    OSL_ASSERT(inArguments.size() == 1);
    css::uno::Sequence< css::bridge::ProtocolProperty > s;
    OSL_VERIFY(mapBinaryToCppAny(inArguments[0]) >>= s);
    for (sal_Int32 i = 0; i != s.getLength(); ++i) {
        if (s[i].Name.equalsAsciiL(
                RTL_CONSTASCII_STRINGPARAM("CurrentContext")))
        {
            ccMode = true;
        } else {
            ccMode = false;
            exc = true;
            ret = mapCppToBinaryAny(
                css::uno::makeAny(
                    css::bridge::InvalidProtocolChangeException(
                        rtl::OUString(
                            RTL_CONSTASCII_USTRINGPARAM(
                                "InvalidProtocolChangeException")),
                        css::uno::Reference< css::uno::XInterface >(), s[i],
                        1)));
            break;
        }
    }
    switch (mode_) {
    case MODE_WAIT:
        getWriter()->sendDirectReply(
            tid, protPropCommit_, exc, ret, std::vector< BinaryAny >());
        if (ccMode) {
            setCurrentContextMode();
            mode_ = MODE_NORMAL;
            getWriter()->unblock();
        } else {
            mode_ = MODE_REQUESTED;
            sendRequestChangeRequest();
        }
        break;
    case MODE_NORMAL_WAIT:
        getWriter()->queueReply(
            tid, protPropCommit_, false, false, ret, std::vector< BinaryAny >(),
            ccMode);
        mode_ = MODE_NORMAL;
        break;
    default:
        throw css::uno::RuntimeException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "URP: unexpected commitChange request received")),
            static_cast< cppu::OWeakObject * >(this));
    }
}

OutgoingRequest Bridge::lastOutgoingRequest(rtl::ByteSequence const & tid) {
    OutgoingRequest req(outgoingRequests_.top(tid));
    outgoingRequests_.pop(tid);
    return req;
}

bool Bridge::isProtocolPropertiesRequest(
    rtl::OUString const & oid, css::uno::TypeDescription const & type) const
{
    return oid == protPropOid_ && type.equals(protPropType_);
}

void Bridge::setCurrentContextMode() {
    osl::MutexGuard g(mutex_);
    currentContextMode_ = true;
}

bool Bridge::isCurrentContextMode() {
    osl::MutexGuard g(mutex_);
    return currentContextMode_;
}

Bridge::~Bridge() {
    if (threadPool_ != 0) {
        uno_threadpool_destroy(threadPool_);
    }
}

css::uno::Reference< css::uno::XInterface > Bridge::getInstance(
    rtl::OUString const & sInstanceName) throw (css::uno::RuntimeException)
{
    if ( sInstanceName.isEmpty() ) {
        throw css::uno::RuntimeException(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "XBridge::getInstance sInstanceName must be non-empty")),
            static_cast< cppu::OWeakObject * >(this));
    }
    for (sal_Int32 i = 0; i != sInstanceName.getLength(); ++i) {
        if (sInstanceName[i] > 0x7F) {
            throw css::io::IOException(
                rtl::OUString(
                    RTL_CONSTASCII_USTRINGPARAM(
                        "XBridge::getInstance sInstanceName contains non-ASCII"
                        " character")),
                css::uno::Reference< css::uno::XInterface >());
        }
    }
    css::uno::TypeDescription ifc(
        cppu::UnoType< css::uno::Reference< css::uno::XInterface > >::get());
    typelib_TypeDescription * p = ifc.get();
    std::vector< BinaryAny > inArgs;
    inArgs.push_back(
        BinaryAny(
            css::uno::TypeDescription(cppu::UnoType< css::uno::Type >::get()),
            &p));
    BinaryAny ret;
    std::vector< BinaryAny> outArgs;
    bool exc = makeCall(
        sInstanceName,
        css::uno::TypeDescription(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.uno.XInterface::queryInterface"))),
        false, inArgs, &ret, &outArgs);
    throwException(exc, ret);
    return css::uno::Reference< css::uno::XInterface >(
        static_cast< css::uno::XInterface * >(
            binaryToCppMapping_.mapInterface(
                *static_cast< uno_Interface ** >(ret.getValue(ifc)),
                ifc.get())),
        css::uno::UNO_REF_NO_ACQUIRE);
}

rtl::OUString Bridge::getName() throw (css::uno::RuntimeException) {
    return name_;
}

rtl::OUString Bridge::getDescription() throw (css::uno::RuntimeException) {
    rtl::OUStringBuffer b(name_);
    b.append(sal_Unicode(':'));
    b.append(connection_->getDescription());
    return b.makeStringAndClear();
}

void Bridge::dispose() throw (css::uno::RuntimeException) {
    terminate();
    // OOo expects dispose to not return while there are still remote calls in
    // progress; an external protocol must ensure that dispose is not called
    // from within an incoming or outgoing remote call, as passive_.wait() would
    // otherwise deadlock:
    passive_.wait();
}

void Bridge::addEventListener(
    css::uno::Reference< css::lang::XEventListener > const & xListener)
    throw (css::uno::RuntimeException)
{
    OSL_ASSERT(xListener.is());
    {
        osl::MutexGuard g(mutex_);
        if (!terminated_) {
            listeners_.push_back(xListener);
            return;
        }
    }
    xListener->disposing(
        css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
}

void Bridge::removeEventListener(
    css::uno::Reference< css::lang::XEventListener > const & aListener)
    throw (css::uno::RuntimeException)
{
    osl::MutexGuard g(mutex_);
    Listeners::iterator i(
        std::find(listeners_.begin(), listeners_.end(), aListener));
    if (i != listeners_.end()) {
        listeners_.erase(i);
    }
}

void Bridge::sendCommitChangeRequest() {
    OSL_ASSERT(mode_ == MODE_REQUESTED || mode_ == MODE_REPLY_1);
    css::uno::Sequence< css::bridge::ProtocolProperty > s(1);
    s[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CurrentContext"));
    std::vector< BinaryAny > a;
    a.push_back(mapCppToBinaryAny(css::uno::makeAny(s)));
    sendProtPropRequest(OutgoingRequest::KIND_COMMIT_CHANGE, a);
}

void Bridge::sendProtPropRequest(
    OutgoingRequest::Kind kind, std::vector< BinaryAny > const & inArguments)
{
    OSL_ASSERT(
        kind == OutgoingRequest::KIND_REQUEST_CHANGE ||
        kind == OutgoingRequest::KIND_COMMIT_CHANGE);
    incrementCalls(false);
    css::uno::TypeDescription member(
        kind == OutgoingRequest::KIND_REQUEST_CHANGE
        ? protPropRequest_ : protPropCommit_);
    PopOutgoingRequest pop(
        outgoingRequests_, protPropTid_, OutgoingRequest(kind, member, false));
    getWriter()->sendDirectRequest(
        protPropTid_, protPropOid_, protPropType_, member, inArguments);
    pop.clear();
}

void Bridge::makeReleaseCall(
    rtl::OUString const & oid, css::uno::TypeDescription const & type)
{
    AttachThread att(threadPool_);
    sendRequest(
        att.getTid(), oid, type,
        css::uno::TypeDescription(
            rtl::OUString(
                RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.uno.XInterface::release"))),
        std::vector< BinaryAny >());
}

void Bridge::sendRequest(
    rtl::ByteSequence const & tid, rtl::OUString const & oid,
    css::uno::TypeDescription const & type,
    css::uno::TypeDescription const & member,
    std::vector< BinaryAny > const & inArguments)
{
    getWriter()->queueRequest(tid, oid, type, member, inArguments);
}

void Bridge::throwException(bool exception, BinaryAny const & value) {
    if (exception) {
        cppu::throwException(mapBinaryToCppAny(value));
    }
}

css::uno::Any Bridge::mapBinaryToCppAny(BinaryAny const & binaryAny) {
    BinaryAny in(binaryAny);
    css::uno::Any out;
    out.~Any();
    uno_copyAndConvertData(
        &out, in.get(),
        css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()).get(),
        binaryToCppMapping_.get());
    return out;
}

bool Bridge::becameUnused() const {
    return stubs_.empty() && proxies_ == 0 && calls_ == 0 && normalCall_;
}

void Bridge::terminateWhenUnused(bool unused) {
    if (unused) {
        // That the current thread considers the bridge unused implies that it
        // is not within an incoming or outgoing remote call (so calling
        // terminate cannot lead to deadlock):
        terminate();
    }
}

}
