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