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