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