/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include "sal/config.h" #include #include #include "boost/noncopyable.hpp" #include "com/sun/star/bridge/XInstanceProvider.hpp" #include "cppuhelper/exc_hlp.hxx" #include "rtl/byteseq.hxx" #include "rtl/ref.hxx" #include "rtl/ustring.hxx" #include "sal/types.h" #include "typelib/typedescription.hxx" #include "uno/dispatcher.hxx" #include "binaryany.hxx" #include "bridge.hxx" #include "currentcontext.hxx" #include "incomingrequest.hxx" #include "specialfunctionids.hxx" namespace binaryurp { namespace { namespace css = com::sun::star; } IncomingRequest::IncomingRequest( rtl::Reference< Bridge > const & bridge, rtl::ByteSequence const & tid, rtl::OUString const & oid, css::uno::UnoInterfaceReference const & object, css::uno::TypeDescription const & type, sal_uInt16 functionId, bool synchronous, css::uno::TypeDescription const & member, bool setter, std::vector< BinaryAny > const & inArguments, bool currentContextMode, css::uno::UnoInterfaceReference const & currentContext): bridge_(bridge), tid_(tid), oid_(oid), object_(object), type_(type), functionId_(functionId), synchronous_(synchronous), member_(member), setter_(setter), inArguments_(inArguments), currentContextMode_(currentContextMode), currentContext_(currentContext) { OSL_ASSERT(bridge.is() && member.is() && member.get()->bComplete); } IncomingRequest::~IncomingRequest() {} void IncomingRequest::execute() const { BinaryAny ret; std::vector< BinaryAny > outArgs; bool isExc; try { bool resetCc = false; css::uno::UnoInterfaceReference oldCc; if (currentContextMode_) { oldCc = current_context::get(); current_context::set(currentContext_); resetCc = true; } try { try { isExc = !execute_throw(&ret, &outArgs); } catch (std::exception & e) { throw css::uno::RuntimeException( (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("caught C++ exception: ")) + rtl::OStringToOUString( rtl::OString(e.what()), RTL_TEXTENCODING_ASCII_US)), css::uno::Reference< css::uno::XInterface >()); // best-effort string conversion } } catch (css::uno::RuntimeException &) { css::uno::Any exc(cppu::getCaughtException()); ret = bridge_->mapCppToBinaryAny(exc); isExc = true; } if (resetCc) { current_context::set(oldCc); } } catch (css::uno::RuntimeException &) { css::uno::Any exc(cppu::getCaughtException()); ret = bridge_->mapCppToBinaryAny(exc); isExc = true; } if (synchronous_) { bridge_->decrementActiveCalls(); try { bridge_->getWriter()->queueReply( tid_, member_, setter_, isExc, ret, outArgs, false); return; } catch (css::uno::RuntimeException & e) { OSL_TRACE( OSL_LOG_PREFIX "caught UNO runtime exception '%s'", (rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8). getStr())); } catch (std::exception & e) { OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what()); } bridge_->terminate(); } else { if (isExc) { OSL_TRACE(OSL_LOG_PREFIX "oneway method raised exception"); } bridge_->decrementCalls(); } } bool IncomingRequest::execute_throw( BinaryAny * returnValue, std::vector< BinaryAny > * outArguments) const { OSL_ASSERT( returnValue != 0 && returnValue->getType().equals( css::uno::TypeDescription( cppu::UnoType< cppu::UnoVoidType >::get())) && outArguments != 0 && outArguments->empty()); bool isExc = false; switch (functionId_) { case SPECIAL_FUNCTION_ID_RESERVED: OSL_ASSERT(false); // this cannot happen break; case SPECIAL_FUNCTION_ID_RELEASE: bridge_->releaseStub(oid_, type_); break; case SPECIAL_FUNCTION_ID_QUERY_INTERFACE: if (!object_.is()) { css::uno::Reference< css::uno::XInterface > ifc; css::uno::Reference< css::bridge::XInstanceProvider > prov( bridge_->getProvider()); if (prov.is()) { try { ifc = prov->getInstance(oid_); } catch (css::container::NoSuchElementException & e) { OSL_TRACE( (OSL_LOG_PREFIX "initial element '%s':" " NoSuchElementException '%s'"), (rtl::OUStringToOString(oid_, RTL_TEXTENCODING_UTF8). getStr()), (rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8). getStr())); } } if (ifc.is()) { css::uno::UnoInterfaceReference unoIfc( static_cast< uno_Interface * >( bridge_->getCppToBinaryMapping().mapInterface( ifc.get(), (css::uno::TypeDescription( cppu::UnoType< css::uno::Reference< css::uno::XInterface > >::get()). get()))), SAL_NO_ACQUIRE); *returnValue = BinaryAny( css::uno::TypeDescription( cppu::UnoType< css::uno::Reference< css::uno::XInterface > >::get()), &unoIfc.m_pUnoI); } break; } // fall through default: { OSL_ASSERT(object_.is()); css::uno::TypeDescription retType; std::list< std::vector< char > > outBufs; std::vector< void * > args; switch (member_.get()->eTypeClass) { case typelib_TypeClass_INTERFACE_ATTRIBUTE: { css::uno::TypeDescription t( reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( member_.get())-> pAttributeTypeRef); if (setter_) { OSL_ASSERT(inArguments_.size() == 1); args.push_back(inArguments_[0].getValue(t)); } else { OSL_ASSERT(inArguments_.empty()); retType = t; } break; } case typelib_TypeClass_INTERFACE_METHOD: { typelib_InterfaceMethodTypeDescription * mtd = reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( member_.get()); retType = css::uno::TypeDescription(mtd->pReturnTypeRef); std::vector< BinaryAny >::const_iterator i( inArguments_.begin()); for (sal_Int32 j = 0; j != mtd->nParams; ++j) { void * p; if (mtd->pParams[j].bIn) { p = i++->getValue( css::uno::TypeDescription( mtd->pParams[j].pTypeRef)); } else { outBufs.push_back( std::vector< char >( css::uno::TypeDescription( mtd->pParams[j].pTypeRef). get()->nSize)); p = &outBufs.back()[0]; } args.push_back(p); if (mtd->pParams[j].bOut) { outArguments->push_back(BinaryAny()); } } OSL_ASSERT(i == inArguments_.end()); break; } default: OSL_ASSERT(false); // this cannot happen break; } std::vector< char > retBuf(retType.is() ? retType.get()->nSize : 0); uno_Any exc; uno_Any * pexc = &exc; (*object_.get()->pDispatcher)( object_.get(), member_.get(), retBuf.empty() ? 0 : &retBuf[0], args.empty() ? 0 : &args[0], &pexc); isExc = pexc != 0; if (isExc) { *returnValue = BinaryAny( css::uno::TypeDescription( cppu::UnoType< css::uno::Any >::get()), &exc); uno_any_destruct(&exc, 0); } else { if (!retBuf.empty()) { *returnValue = BinaryAny(retType, &retBuf[0]); uno_destructData(&retBuf[0], retType.get(), 0); } if (!outArguments->empty()) { OSL_ASSERT( member_.get()->eTypeClass == typelib_TypeClass_INTERFACE_METHOD); typelib_InterfaceMethodTypeDescription * mtd = reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( member_.get()); std::vector< BinaryAny >::iterator i(outArguments->begin()); std::list< std::vector< char > >::iterator j( outBufs.begin()); for (sal_Int32 k = 0; k != mtd->nParams; ++k) { if (mtd->pParams[k].bOut) { *i++ = BinaryAny( css::uno::TypeDescription( mtd->pParams[k].pTypeRef), args[k]); } if (!mtd->pParams[k].bIn) { uno_type_destructData( &(*j++)[0], mtd->pParams[k].pTypeRef, 0); } } OSL_ASSERT(i == outArguments->end()); OSL_ASSERT(j == outBufs.end()); } } break; } } return !isExc; } }