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