xref: /trunk/main/binaryurp/source/proxy.cxx (revision cdf0e10c)
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