update dev300-m58
[ooovba.git] / stoc / source / proxy_factory / proxyfac.cxx
blobac6a1f918e1047d80410b1e6a5b91027ab3bbe2b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: proxyfac.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
34 #include "osl/diagnose.h"
35 #include "osl/interlck.h"
36 #include "osl/doublecheckedlocking.h"
37 #include "osl/mutex.hxx"
38 #include "rtl/ref.hxx"
39 #include "uno/dispatcher.hxx"
40 #include "uno/data.h"
41 #include "uno/mapping.hxx"
42 #include "uno/environment.hxx"
43 #include "typelib/typedescription.hxx"
44 #include "cppuhelper/exc_hlp.hxx"
45 #include "cppuhelper/implbase2.hxx"
46 #include "cppuhelper/implementationentry.hxx"
47 #include "cppuhelper/factory.hxx"
48 #include "com/sun/star/lang/XServiceInfo.hpp"
49 #include "com/sun/star/registry/XRegistryKey.hpp"
50 #include "com/sun/star/reflection/XProxyFactory.hpp"
51 #include "com/sun/star/uno/RuntimeException.hpp"
53 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
54 #define SERVICE_NAME "com.sun.star.reflection.ProxyFactory"
55 #define IMPL_NAME "com.sun.star.comp.reflection.ProxyFactory"
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::uno;
60 using ::rtl::OUString;
63 namespace
66 static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
68 static OUString proxyfac_getImplementationName()
70 return OUSTR(IMPL_NAME);
73 static Sequence< OUString > proxyfac_getSupportedServiceNames()
75 OUString str_name = OUSTR(SERVICE_NAME);
76 return Sequence< OUString >( &str_name, 1 );
79 //==============================================================================
80 struct FactoryImpl : public ::cppu::WeakImplHelper2< lang::XServiceInfo,
81 reflection::XProxyFactory >
83 Environment m_uno_env;
84 Environment m_cpp_env;
85 Mapping m_uno2cpp;
86 Mapping m_cpp2uno;
88 UnoInterfaceReference binuno_queryInterface(
89 UnoInterfaceReference const & unoI,
90 typelib_InterfaceTypeDescription * pTypeDescr );
92 FactoryImpl();
93 virtual ~FactoryImpl();
95 // XServiceInfo
96 virtual OUString SAL_CALL getImplementationName()
97 throw (RuntimeException);
98 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName )
99 throw (RuntimeException);
100 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
101 throw (RuntimeException);
103 // XProxyFactory
104 virtual Reference< XAggregation > SAL_CALL createProxy(
105 Reference< XInterface > const & xTarget )
106 throw (RuntimeException);
109 //______________________________________________________________________________
110 UnoInterfaceReference FactoryImpl::binuno_queryInterface(
111 UnoInterfaceReference const & unoI,
112 typelib_InterfaceTypeDescription * pTypeDescr )
114 // init queryInterface() td
115 static typelib_TypeDescription * s_pQITD = 0;
116 if (s_pQITD == 0)
118 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
119 if (s_pQITD == 0)
121 typelib_TypeDescription * pTXInterfaceDescr = 0;
122 TYPELIB_DANGER_GET(
123 &pTXInterfaceDescr,
124 ::getCppuType( reinterpret_cast< Reference< XInterface >
125 const * >(0) ).getTypeLibType() );
126 typelib_TypeDescription * pQITD = 0;
127 typelib_typedescriptionreference_getDescription(
128 &pQITD, reinterpret_cast< typelib_InterfaceTypeDescription * >(
129 pTXInterfaceDescr )->ppAllMembers[ 0 ] );
130 TYPELIB_DANGER_RELEASE( pTXInterfaceDescr );
131 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
132 s_pQITD = pQITD;
135 else
137 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
140 void * args[ 1 ];
141 args[ 0 ] = &reinterpret_cast< typelib_TypeDescription * >(
142 pTypeDescr )->pWeakRef;
143 uno_Any ret_val, exc_space;
144 uno_Any * exc = &exc_space;
146 unoI.dispatch( s_pQITD, &ret_val, args, &exc );
148 if (exc == 0)
150 UnoInterfaceReference ret;
151 if (ret_val.pType->eTypeClass == typelib_TypeClass_INTERFACE)
153 ret.set( *reinterpret_cast< uno_Interface ** >(ret_val.pData),
154 SAL_NO_ACQUIRE );
155 typelib_typedescriptionreference_release( ret_val.pType );
157 else
159 uno_any_destruct( &ret_val, 0 );
161 return ret;
163 else
165 // exception occured:
166 OSL_ENSURE(
167 typelib_typedescriptionreference_isAssignableFrom(
168 ::getCppuType( reinterpret_cast<
169 RuntimeException const * >(0) ).getTypeLibType(),
170 exc->pType ),
171 "### RuntimeException expected!" );
172 Any cpp_exc;
173 uno_type_copyAndConvertData(
174 &cpp_exc, exc, ::getCppuType( &cpp_exc ).getTypeLibType(),
175 m_uno2cpp.get() );
176 uno_any_destruct( exc, 0 );
177 ::cppu::throwException( cpp_exc );
178 OSL_ASSERT( 0 ); // way of no return
179 return UnoInterfaceReference(); // for dummy
183 //==============================================================================
184 struct ProxyRoot : public ::cppu::OWeakAggObject
186 // XAggregation
187 virtual Any SAL_CALL queryAggregation( Type const & rType )
188 throw (RuntimeException);
190 virtual ~ProxyRoot();
191 inline ProxyRoot( ::rtl::Reference< FactoryImpl > const & factory,
192 Reference< XInterface > const & xTarget );
194 ::rtl::Reference< FactoryImpl > m_factory;
196 private:
197 UnoInterfaceReference m_target;
200 //==============================================================================
201 struct binuno_Proxy : public uno_Interface
203 oslInterlockedCount m_nRefCount;
204 ::rtl::Reference< ProxyRoot > m_root;
205 UnoInterfaceReference m_target;
206 OUString m_oid;
207 TypeDescription m_typeDescr;
209 inline binuno_Proxy(
210 ::rtl::Reference< ProxyRoot > const & root,
211 UnoInterfaceReference const & target,
212 OUString const & oid, TypeDescription const & typeDescr );
215 extern "C"
218 //------------------------------------------------------------------------------
219 static void SAL_CALL binuno_proxy_free(
220 uno_ExtEnvironment * pEnv, void * pProxy )
222 (void) pEnv; // avoid warning about unused parameter
223 binuno_Proxy * proxy = static_cast< binuno_Proxy * >(
224 reinterpret_cast< uno_Interface * >( pProxy ) );
225 OSL_ASSERT( proxy->m_root->m_factory->m_uno_env.get()->pExtEnv == pEnv );
226 delete proxy;
229 //------------------------------------------------------------------------------
230 static void SAL_CALL binuno_proxy_acquire( uno_Interface * pUnoI )
232 binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI );
233 if (osl_incrementInterlockedCount( &that->m_nRefCount ) == 1)
235 // rebirth of zombie
236 uno_ExtEnvironment * uno_env =
237 that->m_root->m_factory->m_uno_env.get()->pExtEnv;
238 OSL_ASSERT( uno_env != 0 );
239 (*uno_env->registerProxyInterface)(
240 uno_env, reinterpret_cast< void ** >( &pUnoI ), binuno_proxy_free,
241 that->m_oid.pData,
242 reinterpret_cast< typelib_InterfaceTypeDescription * >(
243 that->m_typeDescr.get() ) );
244 OSL_ASSERT( that == static_cast< binuno_Proxy * >( pUnoI ) );
248 //------------------------------------------------------------------------------
249 static void SAL_CALL binuno_proxy_release( uno_Interface * pUnoI )
251 binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI );
252 if (osl_decrementInterlockedCount( &that->m_nRefCount ) == 0)
254 uno_ExtEnvironment * uno_env =
255 that->m_root->m_factory->m_uno_env.get()->pExtEnv;
256 OSL_ASSERT( uno_env != 0 );
257 (*uno_env->revokeInterface)( uno_env, pUnoI );
261 //------------------------------------------------------------------------------
262 static void SAL_CALL binuno_proxy_dispatch(
263 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
264 void * pReturn, void * pArgs [], uno_Any ** ppException )
266 binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI );
267 switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription const * >(
268 pMemberType )->nPosition)
270 case 0: // queryInterface()
274 Type const & rType =
275 *reinterpret_cast< Type const * >( pArgs[ 0 ] );
276 Any ret( that->m_root->queryInterface( rType ) );
277 uno_type_copyAndConvertData(
278 pReturn, &ret, ::getCppuType( &ret ).getTypeLibType(),
279 that->m_root->m_factory->m_cpp2uno.get() );
280 *ppException = 0; // no exc
282 catch (RuntimeException &)
284 Any exc( ::cppu::getCaughtException() );
285 uno_type_any_constructAndConvert(
286 *ppException, const_cast< void * >(exc.getValue()),
287 exc.getValueTypeRef(),
288 that->m_root->m_factory->m_cpp2uno.get() );
290 break;
292 case 1: // acquire()
293 binuno_proxy_acquire( pUnoI );
294 *ppException = 0; // no exc
295 break;
296 case 2: // release()
297 binuno_proxy_release( pUnoI );
298 *ppException = 0; // no exc
299 break;
300 default:
301 that->m_target.dispatch( pMemberType, pReturn, pArgs, ppException );
302 break;
308 //______________________________________________________________________________
309 inline binuno_Proxy::binuno_Proxy(
310 ::rtl::Reference< ProxyRoot > const & root,
311 UnoInterfaceReference const & target,
312 OUString const & oid, TypeDescription const & typeDescr )
313 : m_nRefCount( 1 ),
314 m_root( root ),
315 m_target( target ),
316 m_oid( oid ),
317 m_typeDescr( typeDescr )
319 uno_Interface::acquire = binuno_proxy_acquire;
320 uno_Interface::release = binuno_proxy_release;
321 uno_Interface::pDispatcher = binuno_proxy_dispatch;
324 //______________________________________________________________________________
325 ProxyRoot::~ProxyRoot()
329 //______________________________________________________________________________
330 inline ProxyRoot::ProxyRoot(
331 ::rtl::Reference< FactoryImpl > const & factory,
332 Reference< XInterface > const & xTarget )
333 : m_factory( factory )
335 m_factory->m_cpp2uno.mapInterface(
336 reinterpret_cast< void ** >( &m_target.m_pUnoI ), xTarget.get(),
337 ::getCppuType( &xTarget ) );
338 OSL_ENSURE( m_target.is(), "### mapping interface failed!" );
341 //______________________________________________________________________________
342 Any ProxyRoot::queryAggregation( Type const & rType )
343 throw (RuntimeException)
345 Any ret( OWeakAggObject::queryAggregation( rType ) );
346 if (! ret.hasValue())
348 typelib_TypeDescription * pTypeDescr = 0;
349 TYPELIB_DANGER_GET( &pTypeDescr, rType.getTypeLibType() );
352 Reference< XInterface > xProxy;
353 uno_ExtEnvironment * cpp_env = m_factory->m_cpp_env.get()->pExtEnv;
354 OSL_ASSERT( cpp_env != 0 );
356 // mind a new delegator, calculate current root:
357 Reference< XInterface > xRoot(
358 static_cast< OWeakObject * >(this), UNO_QUERY_THROW );
359 OUString oid;
360 (*cpp_env->getObjectIdentifier)( cpp_env, &oid.pData, xRoot.get() );
361 OSL_ASSERT( oid.getLength() > 0 );
363 (*cpp_env->getRegisteredInterface)(
364 cpp_env, reinterpret_cast< void ** >( &xProxy ),
365 oid.pData, reinterpret_cast<
366 typelib_InterfaceTypeDescription * >(pTypeDescr) );
367 if (! xProxy.is())
369 // perform query on target:
370 UnoInterfaceReference proxy_target(
371 m_factory->binuno_queryInterface(
372 m_target, reinterpret_cast<
373 typelib_InterfaceTypeDescription * >(pTypeDescr) ) );
374 if (proxy_target.is())
376 // ensure root's object entries:
377 UnoInterfaceReference root;
378 m_factory->m_cpp2uno.mapInterface(
379 reinterpret_cast< void ** >( &root.m_pUnoI ),
380 xRoot.get(), ::getCppuType( &xRoot ) );
382 UnoInterfaceReference proxy(
383 // ref count initially 1:
384 new binuno_Proxy( this, proxy_target, oid, pTypeDescr ),
385 SAL_NO_ACQUIRE );
386 uno_ExtEnvironment * uno_env =
387 m_factory->m_uno_env.get()->pExtEnv;
388 OSL_ASSERT( uno_env != 0 );
389 (*uno_env->registerProxyInterface)(
390 uno_env, reinterpret_cast< void ** >( &proxy.m_pUnoI ),
391 binuno_proxy_free, oid.pData,
392 reinterpret_cast< typelib_InterfaceTypeDescription * >(
393 pTypeDescr ) );
395 m_factory->m_uno2cpp.mapInterface(
396 reinterpret_cast< void ** >( &xProxy ),
397 proxy.get(), pTypeDescr );
400 if (xProxy.is())
401 ret.setValue( &xProxy, pTypeDescr );
403 catch (...) // finally
405 TYPELIB_DANGER_RELEASE( pTypeDescr );
406 throw;
408 TYPELIB_DANGER_RELEASE( pTypeDescr );
410 return ret;
413 //##############################################################################
415 //______________________________________________________________________________
416 FactoryImpl::FactoryImpl()
418 OUString uno = OUSTR(UNO_LB_UNO);
419 OUString cpp = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
421 uno_getEnvironment(
422 reinterpret_cast< uno_Environment ** >( &m_uno_env ), uno.pData, 0 );
423 OSL_ENSURE( m_uno_env.is(), "### cannot get binary uno env!" );
425 uno_getEnvironment(
426 reinterpret_cast< uno_Environment ** >( &m_cpp_env ), cpp.pData, 0 );
427 OSL_ENSURE( m_cpp_env.is(), "### cannot get C++ uno env!" );
429 uno_getMapping(
430 reinterpret_cast< uno_Mapping ** >( &m_uno2cpp ),
431 m_uno_env.get(), m_cpp_env.get(), 0 );
432 OSL_ENSURE( m_uno2cpp.is(), "### cannot get bridge uno <-> C++!" );
434 uno_getMapping(
435 reinterpret_cast< uno_Mapping ** >( &m_cpp2uno ),
436 m_cpp_env.get(), m_uno_env.get(), 0 );
437 OSL_ENSURE( m_cpp2uno.is(), "### cannot get bridge C++ <-> uno!" );
439 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
442 //______________________________________________________________________________
443 FactoryImpl::~FactoryImpl()
445 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
448 // XProxyFactory
449 //______________________________________________________________________________
450 Reference< XAggregation > FactoryImpl::createProxy(
451 Reference< XInterface > const & xTarget )
452 throw (RuntimeException)
454 return new ProxyRoot( this, xTarget );
457 // XServiceInfo
458 //______________________________________________________________________________
459 OUString FactoryImpl::getImplementationName()
460 throw (RuntimeException)
462 return proxyfac_getImplementationName();;
465 //______________________________________________________________________________
466 sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
467 throw (RuntimeException)
469 Sequence< OUString > const & rSNL = getSupportedServiceNames();
470 OUString const * pArray = rSNL.getConstArray();
471 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
473 if (rServiceName.equals( pArray[ nPos ] ))
474 return true;
476 return false;
479 //______________________________________________________________________________
480 Sequence< OUString > FactoryImpl::getSupportedServiceNames()
481 throw(::com::sun::star::uno::RuntimeException)
483 return proxyfac_getSupportedServiceNames();
486 //==============================================================================
487 static Reference< XInterface > SAL_CALL proxyfac_create(
488 Reference< XComponentContext > const & )
489 throw (Exception)
491 Reference< XInterface > xRet;
493 ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
494 static WeakReference < XInterface > rwInstance;
495 xRet = rwInstance;
497 if (! xRet.is())
499 xRet = static_cast< ::cppu::OWeakObject * >(new FactoryImpl);
500 rwInstance = xRet;
503 return xRet;
506 static ::cppu::ImplementationEntry g_entries [] =
509 proxyfac_create, proxyfac_getImplementationName,
510 proxyfac_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
511 &g_moduleCount.modCnt, 0
513 { 0, 0, 0, 0, 0, 0 }
518 extern "C"
521 sal_Bool SAL_CALL component_canUnload( TimeValue * pTime )
523 return g_moduleCount.canUnload( &g_moduleCount, pTime );
526 void SAL_CALL component_getImplementationEnvironment(
527 const sal_Char ** ppEnvTypeName, uno_Environment ** )
529 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
532 sal_Bool SAL_CALL component_writeInfo(
533 void * pServiceManager, void * pRegistryKey )
535 return ::cppu::component_writeInfoHelper(
536 pServiceManager, pRegistryKey, g_entries );
539 void * SAL_CALL component_getFactory(
540 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
542 return ::cppu::component_getFactoryHelper(
543 pImplName, pServiceManager, pRegistryKey, g_entries );