xref: /aoo4110/main/binaryurp/source/proxy.cxx (revision b1cdbd2c)
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 
proxy_acquireInterface(uno_Interface * pInterface)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 
proxy_releaseInterface(uno_Interface * pInterface)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 
proxy_dispatchInterface(uno_Interface * pUnoI,typelib_TypeDescription const * pMemberType,void * pReturn,void ** pArgs,uno_Any ** ppException)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 
Proxy(rtl::Reference<Bridge> const & bridge,rtl::OUString const & oid,css::uno::TypeDescription const & type)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 
getOid() const82 rtl::OUString Proxy::getOid() const {
83     return oid_;
84 }
85 
getType() const86 css::uno::TypeDescription Proxy::getType() const {
87     return type_;
88 }
89 
do_acquire()90 void Proxy::do_acquire() {
91     if (osl_incrementInterlockedCount(&references_) == 1) {
92         bridge_->resurrectProxy(*this);
93     }
94 }
95 
do_release()96 void Proxy::do_release() {
97     if (osl_decrementInterlockedCount(&references_) == 0) {
98         bridge_->revokeProxy(*this);
99     }
100 }
101 
do_free()102 void Proxy::do_free() {
103     bridge_->freeProxy(*this);
104     delete this;
105 }
106 
do_dispatch(typelib_TypeDescription const * member,void * returnValue,void ** arguments,uno_Any ** exception) const107 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 
isProxy(rtl::Reference<Bridge> const & bridge,css::uno::UnoInterfaceReference const & object,rtl::OUString * oid)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 
~Proxy()142 Proxy::~Proxy() {}
143 
do_dispatch_throw(typelib_TypeDescription const * member,void * returnValue,void ** arguments,uno_Any ** exception) const144 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 
isProxy(rtl::Reference<Bridge> const & bridge,rtl::OUString * oid) const244 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