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 <exception> 27 #include <vector> 28 29 #include "cppuhelper/exc_hlp.hxx" 30 #include "osl/diagnose.h" 31 #include "rtl/ref.hxx" 32 #include "rtl/ustring.hxx" 33 #include "sal/types.h" 34 #include "typelib/typedescription.h" 35 #include "typelib/typedescription.hxx" 36 #include "uno/any2.h" 37 #include "uno/dispatcher.h" 38 #include "uno/dispatcher.hxx" 39 40 #include "binaryany.hxx" 41 #include "bridge.hxx" 42 #include "proxy.hxx" 43 44 namespace binaryurp { 45 46 namespace { 47 48 namespace css = com::sun::star; 49 50 extern "C" void SAL_CALL proxy_acquireInterface(uno_Interface * pInterface) { 51 OSL_ASSERT(pInterface != 0); 52 static_cast< Proxy * >(pInterface)->do_acquire(); 53 } 54 55 extern "C" void SAL_CALL proxy_releaseInterface(uno_Interface * pInterface) { 56 OSL_ASSERT(pInterface != 0); 57 static_cast< Proxy * >(pInterface)->do_release(); 58 } 59 60 extern "C" void SAL_CALL proxy_dispatchInterface( 61 uno_Interface * pUnoI, typelib_TypeDescription const * pMemberType, 62 void * pReturn, void ** pArgs, uno_Any ** ppException) 63 { 64 OSL_ASSERT(pUnoI != 0); 65 static_cast< Proxy * >(pUnoI)->do_dispatch( 66 pMemberType, pReturn, pArgs, ppException); 67 } 68 69 } 70 71 Proxy::Proxy( 72 rtl::Reference< Bridge > const & bridge, rtl::OUString const & oid, 73 css::uno::TypeDescription const & type): 74 bridge_(bridge), oid_(oid), type_(type), references_(1) 75 { 76 OSL_ASSERT(bridge.is()); 77 acquire = &proxy_acquireInterface; 78 release = &proxy_releaseInterface; 79 pDispatcher = &proxy_dispatchInterface; 80 } 81 82 rtl::OUString Proxy::getOid() const { 83 return oid_; 84 } 85 86 css::uno::TypeDescription Proxy::getType() const { 87 return type_; 88 } 89 90 void Proxy::do_acquire() { 91 if (osl_incrementInterlockedCount(&references_) == 1) { 92 bridge_->resurrectProxy(*this); 93 } 94 } 95 96 void Proxy::do_release() { 97 if (osl_decrementInterlockedCount(&references_) == 0) { 98 bridge_->revokeProxy(*this); 99 } 100 } 101 102 void Proxy::do_free() { 103 bridge_->freeProxy(*this); 104 delete this; 105 } 106 107 void Proxy::do_dispatch( 108 typelib_TypeDescription const * member, void * returnValue, 109 void ** arguments, uno_Any ** exception) const 110 { 111 try { 112 try { 113 do_dispatch_throw(member, returnValue, arguments, exception); 114 } catch (std::exception & e) { 115 throw css::uno::RuntimeException( 116 (rtl::OUString( 117 RTL_CONSTASCII_USTRINGPARAM("caught C++ exception: ")) + 118 rtl::OStringToOUString( 119 rtl::OString(e.what()), RTL_TEXTENCODING_ASCII_US)), 120 css::uno::Reference< css::uno::XInterface >()); 121 // best-effort string conversion 122 } 123 } catch (css::uno::RuntimeException &) { 124 css::uno::Any exc(cppu::getCaughtException()); 125 uno_copyAndConvertData( 126 *exception, &exc, 127 (css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()). 128 get()), 129 bridge_->getCppToBinaryMapping().get()); 130 } 131 } 132 133 bool Proxy::isProxy( 134 rtl::Reference< Bridge > const & bridge, 135 css::uno::UnoInterfaceReference const & object, rtl::OUString * oid) 136 { 137 OSL_ASSERT(object.is()); 138 return object.m_pUnoI->acquire == &proxy_acquireInterface && 139 static_cast< Proxy * >(object.m_pUnoI)->isProxy(bridge, oid); 140 } 141 142 Proxy::~Proxy() {} 143 144 void Proxy::do_dispatch_throw( 145 typelib_TypeDescription const * member, void * returnValue, 146 void ** arguments, uno_Any ** exception) const 147 { 148 //TODO: Optimize queryInterface: 149 OSL_ASSERT(member != 0); 150 bool setter = false; 151 std::vector< BinaryAny > inArgs; 152 switch (member->eTypeClass) { 153 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 154 setter = returnValue == 0; 155 if (setter) { 156 inArgs.push_back( 157 BinaryAny( 158 css::uno::TypeDescription( 159 reinterpret_cast< 160 typelib_InterfaceAttributeTypeDescription const * >( 161 member)-> 162 pAttributeTypeRef), 163 arguments[0])); 164 } 165 break; 166 case typelib_TypeClass_INTERFACE_METHOD: 167 { 168 typelib_InterfaceMethodTypeDescription const * mtd = 169 reinterpret_cast< 170 typelib_InterfaceMethodTypeDescription const * >(member); 171 for (sal_Int32 i = 0; i != mtd->nParams; ++i) { 172 if (mtd->pParams[i].bIn) { 173 inArgs.push_back( 174 BinaryAny( 175 css::uno::TypeDescription(mtd->pParams[i].pTypeRef), 176 arguments[i])); 177 } 178 } 179 break; 180 } 181 default: 182 OSL_ASSERT(false); // this cannot happen 183 break; 184 } 185 BinaryAny ret; 186 std::vector< BinaryAny > outArgs; 187 if (bridge_->makeCall( 188 oid_, 189 css::uno::TypeDescription( 190 const_cast< typelib_TypeDescription * >(member)), 191 setter, inArgs, &ret, &outArgs)) 192 { 193 OSL_ASSERT( 194 ret.getType().get()->eTypeClass == typelib_TypeClass_EXCEPTION); 195 uno_any_construct( 196 *exception, ret.getValue(ret.getType()), ret.getType().get(), 0); 197 } else { 198 switch (member->eTypeClass) { 199 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 200 if (!setter) { 201 css::uno::TypeDescription t( 202 reinterpret_cast< 203 typelib_InterfaceAttributeTypeDescription const * >( 204 member)-> 205 pAttributeTypeRef); 206 uno_copyData(returnValue, ret.getValue(t), t.get(), 0); 207 } 208 break; 209 case typelib_TypeClass_INTERFACE_METHOD: 210 { 211 typelib_InterfaceMethodTypeDescription const * mtd = 212 reinterpret_cast< 213 typelib_InterfaceMethodTypeDescription const * >( 214 member); 215 css::uno::TypeDescription t(mtd->pReturnTypeRef); 216 if (t.get()->eTypeClass != typelib_TypeClass_VOID) { 217 uno_copyData(returnValue, ret.getValue(t), t.get(), 0); 218 } 219 std::vector< BinaryAny >::iterator i(outArgs.begin()); 220 for (sal_Int32 j = 0; j != mtd->nParams; ++j) { 221 if (mtd->pParams[j].bOut) { 222 css::uno::TypeDescription pt(mtd->pParams[j].pTypeRef); 223 if (mtd->pParams[j].bIn) { 224 uno_assignData( 225 arguments[j], pt.get(), i++->getValue(pt), 226 pt.get(), 0, 0, 0); 227 } else { 228 uno_copyData( 229 arguments[j], i++->getValue(pt), pt.get(), 0); 230 } 231 } 232 } 233 OSL_ASSERT(i == outArgs.end()); 234 break; 235 } 236 default: 237 OSL_ASSERT(false); // this cannot happen 238 break; 239 } 240 *exception = 0; 241 } 242 } 243 244 bool Proxy::isProxy( 245 rtl::Reference< Bridge > const & bridge, rtl::OUString * oid) const 246 { 247 OSL_ASSERT(oid != 0); 248 if (bridge == bridge_) { 249 *oid = oid_; 250 return true; 251 } else { 252 return false; 253 } 254 } 255 256 } 257