xref: /aoo41x/main/binaryurp/source/writer.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir *
3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir *
5*cdf0e10cSrcweir * Copyright 2000, 2011 Oracle and/or its affiliates.
6*cdf0e10cSrcweir *
7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir *
9*cdf0e10cSrcweir * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir *
11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir *
15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir *
21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir *
26*cdf0e10cSrcweir ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "sal/config.h"
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #include <exception>
31*cdf0e10cSrcweir #include <vector>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include "com/sun/star/connection/XConnection.hpp"
34*cdf0e10cSrcweir #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
35*cdf0e10cSrcweir #include "com/sun/star/uno/XCurrentContext.hpp"
36*cdf0e10cSrcweir #include "cppuhelper/exc_hlp.hxx"
37*cdf0e10cSrcweir #include "osl/mutex.hxx"
38*cdf0e10cSrcweir #include "rtl/memory.h"
39*cdf0e10cSrcweir #include "uno/dispatcher.hxx"
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include "binaryany.hxx"
42*cdf0e10cSrcweir #include "bridge.hxx"
43*cdf0e10cSrcweir #include "currentcontext.hxx"
44*cdf0e10cSrcweir #include "specialfunctionids.hxx"
45*cdf0e10cSrcweir #include "writer.hxx"
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir namespace binaryurp {
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir namespace {
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir namespace css = com::sun::star;
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir bool isProtocolPropertyMessage(rtl::OUString const & oid) {
54*cdf0e10cSrcweir     return oid.equalsAsciiL(
55*cdf0e10cSrcweir         RTL_CONSTASCII_STRINGPARAM("UrpProtocolProperties"));
56*cdf0e10cSrcweir }
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir }
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir Writer::Item::Item() {}
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir Writer::Item::Item(
63*cdf0e10cSrcweir     rtl::ByteSequence const & theTid, rtl::OUString const & theOid,
64*cdf0e10cSrcweir     css::uno::TypeDescription const & theType,
65*cdf0e10cSrcweir     css::uno::TypeDescription const & theMember,
66*cdf0e10cSrcweir     std::vector< BinaryAny > const & inArguments,
67*cdf0e10cSrcweir     css::uno::UnoInterfaceReference const & theCurrentContext):
68*cdf0e10cSrcweir     request(true), tid(theTid), oid(theOid), type(theType), member(theMember),
69*cdf0e10cSrcweir     arguments(inArguments), currentContext(theCurrentContext)
70*cdf0e10cSrcweir {}
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir Writer::Item::Item(
73*cdf0e10cSrcweir     rtl::ByteSequence const & theTid,
74*cdf0e10cSrcweir     css::uno::TypeDescription const & theMember, bool theSetter,
75*cdf0e10cSrcweir     bool theException, BinaryAny const & theReturnValue,
76*cdf0e10cSrcweir     std::vector< BinaryAny > const & outArguments,
77*cdf0e10cSrcweir     bool theSetCurrentContextMode):
78*cdf0e10cSrcweir     request(false), tid(theTid), member(theMember), setter(theSetter),
79*cdf0e10cSrcweir     arguments(outArguments), exception(theException),
80*cdf0e10cSrcweir     returnValue(theReturnValue), setCurrentContextMode(theSetCurrentContextMode)
81*cdf0e10cSrcweir {}
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir Writer::Writer(rtl::Reference< Bridge > const  & bridge):
84*cdf0e10cSrcweir     bridge_(bridge), marshal_(bridge, state_), stop_(false)
85*cdf0e10cSrcweir {
86*cdf0e10cSrcweir     OSL_ASSERT(bridge.is());
87*cdf0e10cSrcweir     acquire();
88*cdf0e10cSrcweir }
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir void Writer::sendDirectRequest(
91*cdf0e10cSrcweir     rtl::ByteSequence const & tid, rtl::OUString const & oid,
92*cdf0e10cSrcweir     css::uno::TypeDescription const & type,
93*cdf0e10cSrcweir     css::uno::TypeDescription const & member,
94*cdf0e10cSrcweir     std::vector< BinaryAny > const & inArguments)
95*cdf0e10cSrcweir {
96*cdf0e10cSrcweir     OSL_ASSERT(!unblocked_.check());
97*cdf0e10cSrcweir     sendRequest(
98*cdf0e10cSrcweir         tid, oid, type, member, inArguments, false,
99*cdf0e10cSrcweir         css::uno::UnoInterfaceReference());
100*cdf0e10cSrcweir }
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir void Writer::sendDirectReply(
103*cdf0e10cSrcweir     rtl::ByteSequence const & tid, css::uno::TypeDescription const & member,
104*cdf0e10cSrcweir     bool exception, BinaryAny const & returnValue,
105*cdf0e10cSrcweir     std::vector< BinaryAny > const & outArguments)
106*cdf0e10cSrcweir {
107*cdf0e10cSrcweir     OSL_ASSERT(!unblocked_.check());
108*cdf0e10cSrcweir     sendReply(tid, member, false, exception, returnValue,outArguments);
109*cdf0e10cSrcweir }
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir void Writer::queueRequest(
112*cdf0e10cSrcweir     rtl::ByteSequence const & tid, rtl::OUString const & oid,
113*cdf0e10cSrcweir     css::uno::TypeDescription const & type,
114*cdf0e10cSrcweir     css::uno::TypeDescription const & member,
115*cdf0e10cSrcweir     std::vector< BinaryAny > const & inArguments)
116*cdf0e10cSrcweir {
117*cdf0e10cSrcweir     css::uno::UnoInterfaceReference cc(current_context::get());
118*cdf0e10cSrcweir     osl::MutexGuard g(mutex_);
119*cdf0e10cSrcweir     queue_.push_back(Item(tid, oid, type, member, inArguments, cc));
120*cdf0e10cSrcweir     items_.set();
121*cdf0e10cSrcweir }
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir void Writer::queueReply(
124*cdf0e10cSrcweir     rtl::ByteSequence const & tid,
125*cdf0e10cSrcweir     com::sun::star::uno::TypeDescription const & member, bool setter,
126*cdf0e10cSrcweir     bool exception, BinaryAny const & returnValue,
127*cdf0e10cSrcweir     std::vector< BinaryAny > const & outArguments, bool setCurrentContextMode)
128*cdf0e10cSrcweir {
129*cdf0e10cSrcweir     osl::MutexGuard g(mutex_);
130*cdf0e10cSrcweir     queue_.push_back(
131*cdf0e10cSrcweir         Item(
132*cdf0e10cSrcweir             tid, member, setter, exception, returnValue, outArguments,
133*cdf0e10cSrcweir             setCurrentContextMode));
134*cdf0e10cSrcweir     items_.set();
135*cdf0e10cSrcweir }
136*cdf0e10cSrcweir 
137*cdf0e10cSrcweir void Writer::unblock() {
138*cdf0e10cSrcweir     // Assumes that osl::Condition::set works as a memory barrier, so that
139*cdf0e10cSrcweir     // changes made by preceeding sendDirectRequest/Reply calls are visible to
140*cdf0e10cSrcweir     // subsequent sendRequest/Reply calls:
141*cdf0e10cSrcweir     unblocked_.set();
142*cdf0e10cSrcweir }
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir void Writer::stop() {
145*cdf0e10cSrcweir     {
146*cdf0e10cSrcweir         osl::MutexGuard g(mutex_);
147*cdf0e10cSrcweir         stop_ = true;
148*cdf0e10cSrcweir     }
149*cdf0e10cSrcweir     unblocked_.set();
150*cdf0e10cSrcweir     items_.set();
151*cdf0e10cSrcweir }
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir Writer::~Writer() {}
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir void Writer::run() {
156*cdf0e10cSrcweir     setName("binaryurpWriter");
157*cdf0e10cSrcweir     try {
158*cdf0e10cSrcweir         unblocked_.wait();
159*cdf0e10cSrcweir         for (;;) {
160*cdf0e10cSrcweir             items_.wait();
161*cdf0e10cSrcweir             Item item;
162*cdf0e10cSrcweir             {
163*cdf0e10cSrcweir                 osl::MutexGuard g(mutex_);
164*cdf0e10cSrcweir                 if (stop_) {
165*cdf0e10cSrcweir                     return;
166*cdf0e10cSrcweir                 }
167*cdf0e10cSrcweir                 OSL_ASSERT(!queue_.empty());
168*cdf0e10cSrcweir                 item = queue_.front();
169*cdf0e10cSrcweir                 queue_.pop_front();
170*cdf0e10cSrcweir                 if (queue_.empty()) {
171*cdf0e10cSrcweir                     items_.reset();
172*cdf0e10cSrcweir                 }
173*cdf0e10cSrcweir             }
174*cdf0e10cSrcweir             if (item.request) {
175*cdf0e10cSrcweir                 sendRequest(
176*cdf0e10cSrcweir                     item.tid, item.oid, item.type, item.member, item.arguments,
177*cdf0e10cSrcweir                     (!item.oid.equalsAsciiL(
178*cdf0e10cSrcweir                         RTL_CONSTASCII_STRINGPARAM("UrpProtocolProperties")) &&
179*cdf0e10cSrcweir                      !item.member.equals(
180*cdf0e10cSrcweir                          css::uno::TypeDescription(
181*cdf0e10cSrcweir                              rtl::OUString(
182*cdf0e10cSrcweir                                  RTL_CONSTASCII_USTRINGPARAM(
183*cdf0e10cSrcweir                                      "com.sun.star.uno.XInterface::"
184*cdf0e10cSrcweir                                      "release")))) &&
185*cdf0e10cSrcweir                      bridge_->isCurrentContextMode()),
186*cdf0e10cSrcweir                     item.currentContext);
187*cdf0e10cSrcweir             } else {
188*cdf0e10cSrcweir                 sendReply(
189*cdf0e10cSrcweir                     item.tid, item.member, item.setter, item.exception,
190*cdf0e10cSrcweir                     item.returnValue, item.arguments);
191*cdf0e10cSrcweir                 if (item.setCurrentContextMode) {
192*cdf0e10cSrcweir                     bridge_->setCurrentContextMode();
193*cdf0e10cSrcweir                 }
194*cdf0e10cSrcweir             }
195*cdf0e10cSrcweir         }
196*cdf0e10cSrcweir     } catch (css::uno::Exception & e) {
197*cdf0e10cSrcweir         OSL_TRACE(
198*cdf0e10cSrcweir             OSL_LOG_PREFIX "caught UNO exception '%s'",
199*cdf0e10cSrcweir             rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
200*cdf0e10cSrcweir     } catch (std::exception & e) {
201*cdf0e10cSrcweir         OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
202*cdf0e10cSrcweir     }
203*cdf0e10cSrcweir     bridge_->terminate();
204*cdf0e10cSrcweir }
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir void Writer::onTerminated() {
207*cdf0e10cSrcweir     release();
208*cdf0e10cSrcweir }
209*cdf0e10cSrcweir 
210*cdf0e10cSrcweir void Writer::sendRequest(
211*cdf0e10cSrcweir     rtl::ByteSequence const & tid, rtl::OUString const & oid,
212*cdf0e10cSrcweir     css::uno::TypeDescription const & type,
213*cdf0e10cSrcweir     css::uno::TypeDescription const & member,
214*cdf0e10cSrcweir     std::vector< BinaryAny > const & inArguments, bool currentContextMode,
215*cdf0e10cSrcweir     css::uno::UnoInterfaceReference const & currentContext)
216*cdf0e10cSrcweir {
217*cdf0e10cSrcweir     OSL_ASSERT(tid.getLength() != 0 && oid.getLength() != 0 && member.is());
218*cdf0e10cSrcweir     css::uno::TypeDescription t(type);
219*cdf0e10cSrcweir     sal_Int32 functionId = 0;
220*cdf0e10cSrcweir     bool forceSynchronous = false;
221*cdf0e10cSrcweir     member.makeComplete();
222*cdf0e10cSrcweir     switch (member.get()->eTypeClass) {
223*cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
224*cdf0e10cSrcweir         {
225*cdf0e10cSrcweir             typelib_InterfaceAttributeTypeDescription * atd =
226*cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
227*cdf0e10cSrcweir                     member.get());
228*cdf0e10cSrcweir             OSL_ASSERT(atd->pInterface != 0);
229*cdf0e10cSrcweir             if (!t.is()) {
230*cdf0e10cSrcweir                 t = css::uno::TypeDescription(&atd->pInterface->aBase);
231*cdf0e10cSrcweir             }
232*cdf0e10cSrcweir             t.makeComplete();
233*cdf0e10cSrcweir             functionId = atd->pInterface->pMapMemberIndexToFunctionIndex[
234*cdf0e10cSrcweir                 atd->aBase.nPosition];
235*cdf0e10cSrcweir             if (!inArguments.empty()) { // setter
236*cdf0e10cSrcweir                 ++functionId;
237*cdf0e10cSrcweir             }
238*cdf0e10cSrcweir             break;
239*cdf0e10cSrcweir         }
240*cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE_METHOD:
241*cdf0e10cSrcweir         {
242*cdf0e10cSrcweir             typelib_InterfaceMethodTypeDescription * mtd =
243*cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
244*cdf0e10cSrcweir                     member.get());
245*cdf0e10cSrcweir             OSL_ASSERT(mtd->pInterface != 0);
246*cdf0e10cSrcweir             if (!t.is()) {
247*cdf0e10cSrcweir                 t = css::uno::TypeDescription(&mtd->pInterface->aBase);
248*cdf0e10cSrcweir             }
249*cdf0e10cSrcweir             t.makeComplete();
250*cdf0e10cSrcweir             functionId = mtd->pInterface->pMapMemberIndexToFunctionIndex[
251*cdf0e10cSrcweir                 mtd->aBase.nPosition];
252*cdf0e10cSrcweir             forceSynchronous = mtd->bOneWay &&
253*cdf0e10cSrcweir                 functionId != SPECIAL_FUNCTION_ID_RELEASE;
254*cdf0e10cSrcweir             break;
255*cdf0e10cSrcweir         }
256*cdf0e10cSrcweir     default:
257*cdf0e10cSrcweir         OSL_ASSERT(false); // this cannot happen
258*cdf0e10cSrcweir         break;
259*cdf0e10cSrcweir     }
260*cdf0e10cSrcweir     OSL_ASSERT(functionId >= 0);
261*cdf0e10cSrcweir     if (functionId > SAL_MAX_UINT16) {
262*cdf0e10cSrcweir         throw css::uno::RuntimeException(
263*cdf0e10cSrcweir             rtl::OUString(
264*cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("function ID too large for URP")),
265*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
266*cdf0e10cSrcweir     }
267*cdf0e10cSrcweir     std::vector< unsigned char > buf;
268*cdf0e10cSrcweir     bool newType = !(lastType_.is() && t.equals(lastType_));
269*cdf0e10cSrcweir     bool newOid = oid != lastOid_;
270*cdf0e10cSrcweir     bool newTid = tid != lastTid_;
271*cdf0e10cSrcweir     if (newType || newOid || newTid || forceSynchronous || functionId > 0x3FFF)
272*cdf0e10cSrcweir         // > 14 bit function ID
273*cdf0e10cSrcweir     {
274*cdf0e10cSrcweir         Marshal::write8(
275*cdf0e10cSrcweir             &buf,
276*cdf0e10cSrcweir             (0xC0 | (newType ? 0x20 : 0) | (newOid ? 0x10 : 0) |
277*cdf0e10cSrcweir              (newTid ? 0x08 : 0) | (functionId > 0xFF ? 0x04 : 0) |
278*cdf0e10cSrcweir              (forceSynchronous ? 0x01 : 0)));
279*cdf0e10cSrcweir             // bit 7: LONGHEADER, bit 6: REQUEST, bit 5: NEWTYPE, bit 4: NEWOID,
280*cdf0e10cSrcweir             // bit 3: NEWTID, bit 2: FUNCTIONID16, bit 0: MOREFLAGS
281*cdf0e10cSrcweir         if (forceSynchronous) {
282*cdf0e10cSrcweir             Marshal::write8(&buf, 0xC0); // bit 7: MUSTREPLY, bit 6: SYNCHRONOUS
283*cdf0e10cSrcweir         }
284*cdf0e10cSrcweir         if (functionId <= 0xFF) {
285*cdf0e10cSrcweir             Marshal::write8(&buf, static_cast< sal_uInt8 >(functionId));
286*cdf0e10cSrcweir         } else {
287*cdf0e10cSrcweir             Marshal::write16(&buf, static_cast< sal_uInt16 >(functionId));
288*cdf0e10cSrcweir         }
289*cdf0e10cSrcweir         if (newType) {
290*cdf0e10cSrcweir             marshal_.writeType(&buf, t);
291*cdf0e10cSrcweir         }
292*cdf0e10cSrcweir         if (newOid) {
293*cdf0e10cSrcweir             marshal_.writeOid(&buf, oid);
294*cdf0e10cSrcweir         }
295*cdf0e10cSrcweir         if (newTid) {
296*cdf0e10cSrcweir             marshal_.writeTid(&buf, tid);
297*cdf0e10cSrcweir         }
298*cdf0e10cSrcweir     } else if (functionId <= 0x3F) { // <= 6 bit function ID
299*cdf0e10cSrcweir         Marshal::write8(&buf, static_cast< sal_uInt8 >(functionId));
300*cdf0e10cSrcweir             // bit 7: !LONGHEADER, bit 6: !FUNCTIONID14
301*cdf0e10cSrcweir     } else {
302*cdf0e10cSrcweir         Marshal::write8(
303*cdf0e10cSrcweir             &buf, static_cast< sal_uInt8 >(0x40 | (functionId >> 8)));
304*cdf0e10cSrcweir             // bit 7: !LONGHEADER, bit 6: FUNCTIONID14
305*cdf0e10cSrcweir         Marshal::write8(&buf, functionId & 0xFF);
306*cdf0e10cSrcweir     }
307*cdf0e10cSrcweir     if (currentContextMode) {
308*cdf0e10cSrcweir         css::uno::UnoInterfaceReference cc(currentContext);
309*cdf0e10cSrcweir         marshal_.writeValue(
310*cdf0e10cSrcweir             &buf,
311*cdf0e10cSrcweir             css::uno::TypeDescription(
312*cdf0e10cSrcweir                 cppu::UnoType<
313*cdf0e10cSrcweir                     css::uno::Reference< css::uno::XCurrentContext > >::get()),
314*cdf0e10cSrcweir             BinaryAny(
315*cdf0e10cSrcweir                 css::uno::TypeDescription(
316*cdf0e10cSrcweir                     cppu::UnoType<
317*cdf0e10cSrcweir                         css::uno::Reference<
318*cdf0e10cSrcweir                             css::uno::XCurrentContext > >::get()),
319*cdf0e10cSrcweir                 &cc.m_pUnoI));
320*cdf0e10cSrcweir     }
321*cdf0e10cSrcweir     switch (member.get()->eTypeClass) {
322*cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
323*cdf0e10cSrcweir         if (!inArguments.empty()) { // setter
324*cdf0e10cSrcweir             OSL_ASSERT(inArguments.size() == 1);
325*cdf0e10cSrcweir             marshal_.writeValue(
326*cdf0e10cSrcweir                 &buf,
327*cdf0e10cSrcweir                 css::uno::TypeDescription(
328*cdf0e10cSrcweir                     reinterpret_cast<
329*cdf0e10cSrcweir                         typelib_InterfaceAttributeTypeDescription * >(
330*cdf0e10cSrcweir                             member.get())->
331*cdf0e10cSrcweir                     pAttributeTypeRef),
332*cdf0e10cSrcweir                 inArguments.front());
333*cdf0e10cSrcweir         }
334*cdf0e10cSrcweir         break;
335*cdf0e10cSrcweir     case typelib_TypeClass_INTERFACE_METHOD:
336*cdf0e10cSrcweir         {
337*cdf0e10cSrcweir             typelib_InterfaceMethodTypeDescription * mtd =
338*cdf0e10cSrcweir                 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
339*cdf0e10cSrcweir                     member.get());
340*cdf0e10cSrcweir             std::vector< BinaryAny >::const_iterator i(inArguments.begin());
341*cdf0e10cSrcweir             for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
342*cdf0e10cSrcweir                 if (mtd->pParams[j].bIn) {
343*cdf0e10cSrcweir                     marshal_.writeValue(
344*cdf0e10cSrcweir                         &buf,
345*cdf0e10cSrcweir                         css::uno::TypeDescription(mtd->pParams[j].pTypeRef),
346*cdf0e10cSrcweir                         *i++);
347*cdf0e10cSrcweir                 }
348*cdf0e10cSrcweir             }
349*cdf0e10cSrcweir             OSL_ASSERT(i == inArguments.end());
350*cdf0e10cSrcweir             break;
351*cdf0e10cSrcweir         }
352*cdf0e10cSrcweir     default:
353*cdf0e10cSrcweir         OSL_ASSERT(false); // this cannot happen
354*cdf0e10cSrcweir         break;
355*cdf0e10cSrcweir     }
356*cdf0e10cSrcweir     sendMessage(buf);
357*cdf0e10cSrcweir     lastType_ = t;
358*cdf0e10cSrcweir     lastOid_ = oid;
359*cdf0e10cSrcweir     lastTid_ = tid;
360*cdf0e10cSrcweir }
361*cdf0e10cSrcweir 
362*cdf0e10cSrcweir void Writer::sendReply(
363*cdf0e10cSrcweir     rtl::ByteSequence const & tid,
364*cdf0e10cSrcweir     com::sun::star::uno::TypeDescription const & member, bool setter,
365*cdf0e10cSrcweir     bool exception, BinaryAny const & returnValue,
366*cdf0e10cSrcweir     std::vector< BinaryAny > const & outArguments)
367*cdf0e10cSrcweir {
368*cdf0e10cSrcweir     OSL_ASSERT(tid.getLength() != 0 && member.is() && member.get()->bComplete);
369*cdf0e10cSrcweir     std::vector< unsigned char > buf;
370*cdf0e10cSrcweir     bool newTid = tid != lastTid_;
371*cdf0e10cSrcweir     Marshal::write8(&buf, 0x80 | (exception ? 0x20 : 0) | (newTid ? 0x08 : 0));
372*cdf0e10cSrcweir         // bit 7: LONGHEADER; bit 6: !REQUEST; bit 5: EXCEPTION; bit 3: NEWTID
373*cdf0e10cSrcweir     if (newTid) {
374*cdf0e10cSrcweir         marshal_.writeTid(&buf, tid);
375*cdf0e10cSrcweir     }
376*cdf0e10cSrcweir     if (exception) {
377*cdf0e10cSrcweir         marshal_.writeValue(
378*cdf0e10cSrcweir             &buf,
379*cdf0e10cSrcweir             css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()),
380*cdf0e10cSrcweir             returnValue);
381*cdf0e10cSrcweir     } else {
382*cdf0e10cSrcweir         switch (member.get()->eTypeClass) {
383*cdf0e10cSrcweir         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
384*cdf0e10cSrcweir             if (!setter) {
385*cdf0e10cSrcweir                 marshal_.writeValue(
386*cdf0e10cSrcweir                     &buf,
387*cdf0e10cSrcweir                     css::uno::TypeDescription(
388*cdf0e10cSrcweir                         reinterpret_cast<
389*cdf0e10cSrcweir                             typelib_InterfaceAttributeTypeDescription * >(
390*cdf0e10cSrcweir                                 member.get())->
391*cdf0e10cSrcweir                         pAttributeTypeRef),
392*cdf0e10cSrcweir                     returnValue);
393*cdf0e10cSrcweir             }
394*cdf0e10cSrcweir             break;
395*cdf0e10cSrcweir         case typelib_TypeClass_INTERFACE_METHOD:
396*cdf0e10cSrcweir             {
397*cdf0e10cSrcweir                 typelib_InterfaceMethodTypeDescription * mtd =
398*cdf0e10cSrcweir                     reinterpret_cast<
399*cdf0e10cSrcweir                         typelib_InterfaceMethodTypeDescription * >(
400*cdf0e10cSrcweir                             member.get());
401*cdf0e10cSrcweir                 marshal_.writeValue(
402*cdf0e10cSrcweir                     &buf, css::uno::TypeDescription(mtd->pReturnTypeRef),
403*cdf0e10cSrcweir                     returnValue);
404*cdf0e10cSrcweir                 std::vector< BinaryAny >::const_iterator i(
405*cdf0e10cSrcweir                     outArguments.begin());
406*cdf0e10cSrcweir                 for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
407*cdf0e10cSrcweir                     if (mtd->pParams[j].bOut) {
408*cdf0e10cSrcweir                         marshal_.writeValue(
409*cdf0e10cSrcweir                             &buf,
410*cdf0e10cSrcweir                             css::uno::TypeDescription(mtd->pParams[j].pTypeRef),
411*cdf0e10cSrcweir                             *i++);
412*cdf0e10cSrcweir                     }
413*cdf0e10cSrcweir                 }
414*cdf0e10cSrcweir                 OSL_ASSERT(i == outArguments.end());
415*cdf0e10cSrcweir                 break;
416*cdf0e10cSrcweir             }
417*cdf0e10cSrcweir         default:
418*cdf0e10cSrcweir             OSL_ASSERT(false); // this cannot happen
419*cdf0e10cSrcweir             break;
420*cdf0e10cSrcweir         }
421*cdf0e10cSrcweir     }
422*cdf0e10cSrcweir     sendMessage(buf);
423*cdf0e10cSrcweir     lastTid_ = tid;
424*cdf0e10cSrcweir     bridge_->decrementCalls();
425*cdf0e10cSrcweir }
426*cdf0e10cSrcweir 
427*cdf0e10cSrcweir void Writer::sendMessage(std::vector< unsigned char > const & buffer) {
428*cdf0e10cSrcweir     std::vector< unsigned char > header;
429*cdf0e10cSrcweir     if (buffer.size() > SAL_MAX_UINT32) {
430*cdf0e10cSrcweir         throw css::uno::RuntimeException(
431*cdf0e10cSrcweir             rtl::OUString(
432*cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("message too large for URP")),
433*cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
434*cdf0e10cSrcweir     }
435*cdf0e10cSrcweir     Marshal::write32(&header, static_cast< sal_uInt32 >(buffer.size()));
436*cdf0e10cSrcweir     Marshal::write32(&header, 1);
437*cdf0e10cSrcweir     OSL_ASSERT(!buffer.empty());
438*cdf0e10cSrcweir     unsigned char const * p = &buffer[0];
439*cdf0e10cSrcweir     std::vector< unsigned char >::size_type n = buffer.size();
440*cdf0e10cSrcweir     OSL_ASSERT(header.size() <= SAL_MAX_INT32 && SAL_MAX_INT32 <= SAL_MAX_SIZE);
441*cdf0e10cSrcweir     sal_Size k = SAL_MAX_INT32 - header.size();
442*cdf0e10cSrcweir     if (n < k) {
443*cdf0e10cSrcweir         k = static_cast< sal_Size >(n);
444*cdf0e10cSrcweir     }
445*cdf0e10cSrcweir     css::uno::Sequence< sal_Int8 > s(
446*cdf0e10cSrcweir         static_cast< sal_Int32 >(header.size() + k));
447*cdf0e10cSrcweir     OSL_ASSERT(!header.empty());
448*cdf0e10cSrcweir     rtl_copyMemory(
449*cdf0e10cSrcweir         s.getArray(), &header[0], static_cast< sal_Size >(header.size()));
450*cdf0e10cSrcweir     for (;;) {
451*cdf0e10cSrcweir         rtl_copyMemory(s.getArray() + s.getLength() - k, p, k);
452*cdf0e10cSrcweir         try {
453*cdf0e10cSrcweir             bridge_->getConnection()->write(s);
454*cdf0e10cSrcweir         } catch (css::io::IOException & e) {
455*cdf0e10cSrcweir             css::uno::Any exc(cppu::getCaughtException());
456*cdf0e10cSrcweir             throw css::lang::WrappedTargetRuntimeException(
457*cdf0e10cSrcweir                 (rtl::OUString(
458*cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM(
459*cdf0e10cSrcweir                         "Binary URP write raised IO exception: ")) +
460*cdf0e10cSrcweir                  e.Message),
461*cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >(), exc);
462*cdf0e10cSrcweir         }
463*cdf0e10cSrcweir         n = static_cast< std::vector< unsigned char >::size_type >(n - k);
464*cdf0e10cSrcweir         if (n == 0) {
465*cdf0e10cSrcweir             break;
466*cdf0e10cSrcweir         }
467*cdf0e10cSrcweir         p += k;
468*cdf0e10cSrcweir         k = SAL_MAX_INT32;
469*cdf0e10cSrcweir         if (n < k) {
470*cdf0e10cSrcweir             k = static_cast< sal_Size >(n);
471*cdf0e10cSrcweir         }
472*cdf0e10cSrcweir         s.realloc(k);
473*cdf0e10cSrcweir     }
474*cdf0e10cSrcweir }
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir }
477