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