1*37adc4f0SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*37adc4f0SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*37adc4f0SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*37adc4f0SAndrew Rist * distributed with this work for additional information 6*37adc4f0SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*37adc4f0SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*37adc4f0SAndrew Rist * "License"); you may not use this file except in compliance 9*37adc4f0SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*37adc4f0SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*37adc4f0SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*37adc4f0SAndrew Rist * software distributed under the License is distributed on an 15*37adc4f0SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*37adc4f0SAndrew Rist * KIND, either express or implied. See the License for the 17*37adc4f0SAndrew Rist * specific language governing permissions and limitations 18*37adc4f0SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*37adc4f0SAndrew Rist *************************************************************/ 21*37adc4f0SAndrew Rist 22*37adc4f0SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "sal/config.h" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include <list> 27cdf0e10cSrcweir #include <vector> 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include "boost/noncopyable.hpp" 30cdf0e10cSrcweir #include "com/sun/star/bridge/XInstanceProvider.hpp" 31cdf0e10cSrcweir #include "cppuhelper/exc_hlp.hxx" 32cdf0e10cSrcweir #include "rtl/byteseq.hxx" 33cdf0e10cSrcweir #include "rtl/ref.hxx" 34cdf0e10cSrcweir #include "rtl/ustring.hxx" 35cdf0e10cSrcweir #include "sal/types.h" 36cdf0e10cSrcweir #include "typelib/typedescription.hxx" 37cdf0e10cSrcweir #include "uno/dispatcher.hxx" 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include "binaryany.hxx" 40cdf0e10cSrcweir #include "bridge.hxx" 41cdf0e10cSrcweir #include "currentcontext.hxx" 42cdf0e10cSrcweir #include "incomingrequest.hxx" 43cdf0e10cSrcweir #include "specialfunctionids.hxx" 44cdf0e10cSrcweir 45cdf0e10cSrcweir namespace binaryurp { 46cdf0e10cSrcweir 47cdf0e10cSrcweir namespace { 48cdf0e10cSrcweir 49cdf0e10cSrcweir namespace css = com::sun::star; 50cdf0e10cSrcweir 51cdf0e10cSrcweir } 52cdf0e10cSrcweir 53cdf0e10cSrcweir IncomingRequest::IncomingRequest( 54cdf0e10cSrcweir rtl::Reference< Bridge > const & bridge, rtl::ByteSequence const & tid, 55cdf0e10cSrcweir rtl::OUString const & oid, css::uno::UnoInterfaceReference const & object, 56cdf0e10cSrcweir css::uno::TypeDescription const & type, sal_uInt16 functionId, 57cdf0e10cSrcweir bool synchronous, css::uno::TypeDescription const & member, bool setter, 58cdf0e10cSrcweir std::vector< BinaryAny > const & inArguments, bool currentContextMode, 59cdf0e10cSrcweir css::uno::UnoInterfaceReference const & currentContext): 60cdf0e10cSrcweir bridge_(bridge), tid_(tid), oid_(oid), object_(object), type_(type), 61cdf0e10cSrcweir functionId_(functionId), synchronous_(synchronous), member_(member), 62cdf0e10cSrcweir setter_(setter), inArguments_(inArguments), 63cdf0e10cSrcweir currentContextMode_(currentContextMode), currentContext_(currentContext) 64cdf0e10cSrcweir { 65cdf0e10cSrcweir OSL_ASSERT(bridge.is() && member.is() && member.get()->bComplete); 66cdf0e10cSrcweir } 67cdf0e10cSrcweir 68cdf0e10cSrcweir IncomingRequest::~IncomingRequest() {} 69cdf0e10cSrcweir 70cdf0e10cSrcweir void IncomingRequest::execute() const { 71cdf0e10cSrcweir BinaryAny ret; 72cdf0e10cSrcweir std::vector< BinaryAny > outArgs; 73cdf0e10cSrcweir bool isExc; 74cdf0e10cSrcweir try { 75cdf0e10cSrcweir bool resetCc = false; 76cdf0e10cSrcweir css::uno::UnoInterfaceReference oldCc; 77cdf0e10cSrcweir if (currentContextMode_) { 78cdf0e10cSrcweir oldCc = current_context::get(); 79cdf0e10cSrcweir current_context::set(currentContext_); 80cdf0e10cSrcweir resetCc = true; 81cdf0e10cSrcweir } 82cdf0e10cSrcweir try { 83cdf0e10cSrcweir try { 84cdf0e10cSrcweir isExc = !execute_throw(&ret, &outArgs); 85cdf0e10cSrcweir } catch (std::exception & e) { 86cdf0e10cSrcweir throw css::uno::RuntimeException( 87cdf0e10cSrcweir (rtl::OUString( 88cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("caught C++ exception: ")) + 89cdf0e10cSrcweir rtl::OStringToOUString( 90cdf0e10cSrcweir rtl::OString(e.what()), RTL_TEXTENCODING_ASCII_US)), 91cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >()); 92cdf0e10cSrcweir // best-effort string conversion 93cdf0e10cSrcweir } 94cdf0e10cSrcweir } catch (css::uno::RuntimeException &) { 95cdf0e10cSrcweir css::uno::Any exc(cppu::getCaughtException()); 96cdf0e10cSrcweir ret = bridge_->mapCppToBinaryAny(exc); 97cdf0e10cSrcweir isExc = true; 98cdf0e10cSrcweir } 99cdf0e10cSrcweir if (resetCc) { 100cdf0e10cSrcweir current_context::set(oldCc); 101cdf0e10cSrcweir } 102cdf0e10cSrcweir } catch (css::uno::RuntimeException &) { 103cdf0e10cSrcweir css::uno::Any exc(cppu::getCaughtException()); 104cdf0e10cSrcweir ret = bridge_->mapCppToBinaryAny(exc); 105cdf0e10cSrcweir isExc = true; 106cdf0e10cSrcweir } 107cdf0e10cSrcweir if (synchronous_) { 108cdf0e10cSrcweir bridge_->decrementActiveCalls(); 109cdf0e10cSrcweir try { 110cdf0e10cSrcweir bridge_->getWriter()->queueReply( 111cdf0e10cSrcweir tid_, member_, setter_, isExc, ret, outArgs, false); 112cdf0e10cSrcweir return; 113cdf0e10cSrcweir } catch (css::uno::RuntimeException & e) { 114cdf0e10cSrcweir OSL_TRACE( 115cdf0e10cSrcweir OSL_LOG_PREFIX "caught UNO runtime exception '%s'", 116cdf0e10cSrcweir (rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8). 117cdf0e10cSrcweir getStr())); 118cdf0e10cSrcweir } catch (std::exception & e) { 119cdf0e10cSrcweir OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what()); 120cdf0e10cSrcweir } 121cdf0e10cSrcweir bridge_->terminate(); 122cdf0e10cSrcweir } else { 123cdf0e10cSrcweir if (isExc) { 124cdf0e10cSrcweir OSL_TRACE(OSL_LOG_PREFIX "oneway method raised exception"); 125cdf0e10cSrcweir } 126cdf0e10cSrcweir bridge_->decrementCalls(); 127cdf0e10cSrcweir } 128cdf0e10cSrcweir } 129cdf0e10cSrcweir 130cdf0e10cSrcweir bool IncomingRequest::execute_throw( 131cdf0e10cSrcweir BinaryAny * returnValue, std::vector< BinaryAny > * outArguments) const 132cdf0e10cSrcweir { 133cdf0e10cSrcweir OSL_ASSERT( 134cdf0e10cSrcweir returnValue != 0 && 135cdf0e10cSrcweir returnValue->getType().equals( 136cdf0e10cSrcweir css::uno::TypeDescription( 137cdf0e10cSrcweir cppu::UnoType< cppu::UnoVoidType >::get())) && 138cdf0e10cSrcweir outArguments != 0 && outArguments->empty()); 139cdf0e10cSrcweir bool isExc = false; 140cdf0e10cSrcweir switch (functionId_) { 141cdf0e10cSrcweir case SPECIAL_FUNCTION_ID_RESERVED: 142cdf0e10cSrcweir OSL_ASSERT(false); // this cannot happen 143cdf0e10cSrcweir break; 144cdf0e10cSrcweir case SPECIAL_FUNCTION_ID_RELEASE: 145cdf0e10cSrcweir bridge_->releaseStub(oid_, type_); 146cdf0e10cSrcweir break; 147cdf0e10cSrcweir case SPECIAL_FUNCTION_ID_QUERY_INTERFACE: 148cdf0e10cSrcweir if (!object_.is()) { 149cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface > ifc; 150cdf0e10cSrcweir css::uno::Reference< css::bridge::XInstanceProvider > prov( 151cdf0e10cSrcweir bridge_->getProvider()); 152cdf0e10cSrcweir if (prov.is()) { 153cdf0e10cSrcweir try { 154cdf0e10cSrcweir ifc = prov->getInstance(oid_); 155cdf0e10cSrcweir } catch (css::container::NoSuchElementException & e) { 156cdf0e10cSrcweir OSL_TRACE( 157cdf0e10cSrcweir (OSL_LOG_PREFIX "initial element '%s':" 158cdf0e10cSrcweir " NoSuchElementException '%s'"), 159cdf0e10cSrcweir (rtl::OUStringToOString(oid_, RTL_TEXTENCODING_UTF8). 160cdf0e10cSrcweir getStr()), 161cdf0e10cSrcweir (rtl::OUStringToOString( 162cdf0e10cSrcweir e.Message, RTL_TEXTENCODING_UTF8). 163cdf0e10cSrcweir getStr())); 164cdf0e10cSrcweir } 165cdf0e10cSrcweir } 166cdf0e10cSrcweir if (ifc.is()) { 167cdf0e10cSrcweir css::uno::UnoInterfaceReference unoIfc( 168cdf0e10cSrcweir static_cast< uno_Interface * >( 169cdf0e10cSrcweir bridge_->getCppToBinaryMapping().mapInterface( 170cdf0e10cSrcweir ifc.get(), 171cdf0e10cSrcweir (css::uno::TypeDescription( 172cdf0e10cSrcweir cppu::UnoType< 173cdf0e10cSrcweir css::uno::Reference< 174cdf0e10cSrcweir css::uno::XInterface > >::get()). 175cdf0e10cSrcweir get()))), 176cdf0e10cSrcweir SAL_NO_ACQUIRE); 177cdf0e10cSrcweir *returnValue = BinaryAny( 178cdf0e10cSrcweir css::uno::TypeDescription( 179cdf0e10cSrcweir cppu::UnoType< 180cdf0e10cSrcweir css::uno::Reference< 181cdf0e10cSrcweir css::uno::XInterface > >::get()), 182cdf0e10cSrcweir &unoIfc.m_pUnoI); 183cdf0e10cSrcweir } 184cdf0e10cSrcweir break; 185cdf0e10cSrcweir } 186cdf0e10cSrcweir // fall through 187cdf0e10cSrcweir default: 188cdf0e10cSrcweir { 189cdf0e10cSrcweir OSL_ASSERT(object_.is()); 190cdf0e10cSrcweir css::uno::TypeDescription retType; 191cdf0e10cSrcweir std::list< std::vector< char > > outBufs; 192cdf0e10cSrcweir std::vector< void * > args; 193cdf0e10cSrcweir switch (member_.get()->eTypeClass) { 194cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_ATTRIBUTE: 195cdf0e10cSrcweir { 196cdf0e10cSrcweir css::uno::TypeDescription t( 197cdf0e10cSrcweir reinterpret_cast< 198cdf0e10cSrcweir typelib_InterfaceAttributeTypeDescription * >( 199cdf0e10cSrcweir member_.get())-> 200cdf0e10cSrcweir pAttributeTypeRef); 201cdf0e10cSrcweir if (setter_) { 202cdf0e10cSrcweir OSL_ASSERT(inArguments_.size() == 1); 203cdf0e10cSrcweir args.push_back(inArguments_[0].getValue(t)); 204cdf0e10cSrcweir } else { 205cdf0e10cSrcweir OSL_ASSERT(inArguments_.empty()); 206cdf0e10cSrcweir retType = t; 207cdf0e10cSrcweir } 208cdf0e10cSrcweir break; 209cdf0e10cSrcweir } 210cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_METHOD: 211cdf0e10cSrcweir { 212cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * mtd = 213cdf0e10cSrcweir reinterpret_cast< 214cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * >( 215cdf0e10cSrcweir member_.get()); 216cdf0e10cSrcweir retType = css::uno::TypeDescription(mtd->pReturnTypeRef); 217cdf0e10cSrcweir std::vector< BinaryAny >::const_iterator i( 218cdf0e10cSrcweir inArguments_.begin()); 219cdf0e10cSrcweir for (sal_Int32 j = 0; j != mtd->nParams; ++j) { 220cdf0e10cSrcweir void * p; 221cdf0e10cSrcweir if (mtd->pParams[j].bIn) { 222cdf0e10cSrcweir p = i++->getValue( 223cdf0e10cSrcweir css::uno::TypeDescription( 224cdf0e10cSrcweir mtd->pParams[j].pTypeRef)); 225cdf0e10cSrcweir } else { 226cdf0e10cSrcweir outBufs.push_back( 227cdf0e10cSrcweir std::vector< char >( 228cdf0e10cSrcweir css::uno::TypeDescription( 229cdf0e10cSrcweir mtd->pParams[j].pTypeRef). 230cdf0e10cSrcweir get()->nSize)); 231cdf0e10cSrcweir p = &outBufs.back()[0]; 232cdf0e10cSrcweir } 233cdf0e10cSrcweir args.push_back(p); 234cdf0e10cSrcweir if (mtd->pParams[j].bOut) { 235cdf0e10cSrcweir outArguments->push_back(BinaryAny()); 236cdf0e10cSrcweir } 237cdf0e10cSrcweir } 238cdf0e10cSrcweir OSL_ASSERT(i == inArguments_.end()); 239cdf0e10cSrcweir break; 240cdf0e10cSrcweir } 241cdf0e10cSrcweir default: 242cdf0e10cSrcweir OSL_ASSERT(false); // this cannot happen 243cdf0e10cSrcweir break; 244cdf0e10cSrcweir } 245cdf0e10cSrcweir std::vector< char > retBuf(retType.is() ? retType.get()->nSize : 0); 246cdf0e10cSrcweir uno_Any exc; 247cdf0e10cSrcweir uno_Any * pexc = &exc; 248cdf0e10cSrcweir (*object_.get()->pDispatcher)( 249cdf0e10cSrcweir object_.get(), member_.get(), retBuf.empty() ? 0 : &retBuf[0], 250cdf0e10cSrcweir args.empty() ? 0 : &args[0], &pexc); 251cdf0e10cSrcweir isExc = pexc != 0; 252cdf0e10cSrcweir if (isExc) { 253cdf0e10cSrcweir *returnValue = BinaryAny( 254cdf0e10cSrcweir css::uno::TypeDescription( 255cdf0e10cSrcweir cppu::UnoType< css::uno::Any >::get()), 256cdf0e10cSrcweir &exc); 257cdf0e10cSrcweir uno_any_destruct(&exc, 0); 258cdf0e10cSrcweir } else { 259cdf0e10cSrcweir if (!retBuf.empty()) { 260cdf0e10cSrcweir *returnValue = BinaryAny(retType, &retBuf[0]); 261cdf0e10cSrcweir uno_destructData(&retBuf[0], retType.get(), 0); 262cdf0e10cSrcweir } 263cdf0e10cSrcweir if (!outArguments->empty()) { 264cdf0e10cSrcweir OSL_ASSERT( 265cdf0e10cSrcweir member_.get()->eTypeClass == 266cdf0e10cSrcweir typelib_TypeClass_INTERFACE_METHOD); 267cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * mtd = 268cdf0e10cSrcweir reinterpret_cast< 269cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * >( 270cdf0e10cSrcweir member_.get()); 271cdf0e10cSrcweir std::vector< BinaryAny >::iterator i(outArguments->begin()); 272cdf0e10cSrcweir std::list< std::vector< char > >::iterator j( 273cdf0e10cSrcweir outBufs.begin()); 274cdf0e10cSrcweir for (sal_Int32 k = 0; k != mtd->nParams; ++k) { 275cdf0e10cSrcweir if (mtd->pParams[k].bOut) { 276cdf0e10cSrcweir *i++ = BinaryAny( 277cdf0e10cSrcweir css::uno::TypeDescription( 278cdf0e10cSrcweir mtd->pParams[k].pTypeRef), 279cdf0e10cSrcweir args[k]); 280cdf0e10cSrcweir } 281cdf0e10cSrcweir if (!mtd->pParams[k].bIn) { 282cdf0e10cSrcweir uno_type_destructData( 283cdf0e10cSrcweir &(*j++)[0], mtd->pParams[k].pTypeRef, 0); 284cdf0e10cSrcweir } 285cdf0e10cSrcweir } 286cdf0e10cSrcweir OSL_ASSERT(i == outArguments->end()); 287cdf0e10cSrcweir OSL_ASSERT(j == outBufs.end()); 288cdf0e10cSrcweir } 289cdf0e10cSrcweir } 290cdf0e10cSrcweir break; 291cdf0e10cSrcweir } 292cdf0e10cSrcweir } 293cdf0e10cSrcweir return !isExc; 294cdf0e10cSrcweir } 295cdf0e10cSrcweir 296cdf0e10cSrcweir } 297