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