update dev300-m58
[ooovba.git] / bridges / source / remote / urp / urp_job.cxx
blob7bfcde4b7275cfd4087b2979bea106a83731a1a4
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: urp_job.cxx,v $
10 * $Revision: 1.17 $
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_bridges.hxx"
33 #include <string.h>
34 #include <stdio.h>
35 #include <osl/diagnose.h>
36 #include <osl/mutex.hxx>
38 #include <rtl/alloc.h>
39 #include <rtl/ustrbuf.hxx>
41 #include <uno/current_context.h>
42 #include <uno/current_context.hxx>
43 #include <uno/threadpool.h>
45 #include <bridges/cpp_uno/type_misc.hxx>
46 #include <bridges/remote/proxy.hxx>
48 #include <com/sun/star/uno/Any.hxx>
49 #include <com/sun/star/uno/XCurrentContext.hpp>
50 #include <com/sun/star/lang/DisposedException.hpp>
52 #include "urp_job.hxx"
53 #include "urp_bridgeimpl.hxx"
54 #include "urp_writer.hxx"
55 #include "urp_dispatch.hxx"
56 #include "urp_log.hxx"
57 #include "urp_marshal.hxx"
58 #include "urp_propertyobject.hxx"
59 #include "urp_reader.hxx"
61 using namespace ::std;
62 using namespace ::rtl;
63 using namespace ::osl;
64 using namespace ::com::sun::star::uno;
66 using namespace bridges_urp;
68 extern "C" {
70 static void SAL_CALL doit(void * job) {
71 ServerMultiJob * p = static_cast< ServerMultiJob * >(job);
72 p->execute();
73 delete p;
78 namespace bridges_urp
80 static sal_Bool isDisposedExceptionDescriptionAvail( const Type &type )
82 static sal_Bool bInit;
83 static sal_Bool bReturn;
84 // we don't care for thread safety here, as both threads must come
85 // to the same result
86 if( ! bInit )
88 typelib_TypeDescription *pTD = 0;
89 typelib_typedescriptionreference_getDescription( & pTD, type.getTypeLibType() );
90 if( pTD )
92 bReturn = sal_True;
93 typelib_typedescription_release( pTD );
95 else
97 bReturn = sal_False;
99 bInit = sal_True;
101 return bReturn;
104 //--------------------------------------------------------------------------------------
105 static void prepareRuntimeExceptionClientSide( uno_Any **ppException , const OUString &s)
107 com::sun::star::lang::DisposedException exception( s , Reference< XInterface > () );
108 Type type = ::getCppuType( &exception );
109 if( !isDisposedExceptionDescriptionAvail( type ) )
111 // if it is not available (probably missing type library),
112 // then we are satisfied with throwing a normal runtime exception,
113 // for which cppu provides a static description
114 type = getCppuType( ( RuntimeException * ) 0 );
116 uno_type_any_construct( *ppException , &exception , type.getTypeLibType() , 0 );
120 Job::Job( uno_Environment *pEnvRemote,
121 remote_Context *pContext,
122 sal_Sequence *pTid,
123 struct urp_BridgeImpl *pBridgeImpl,
124 Unmarshal *pUnmarshal )
125 : m_pContext( pContext )
126 , m_pUnmarshal( pUnmarshal )
127 , m_pBridgeImpl( pBridgeImpl )
128 , m_pTid( pTid )
129 , m_counter( pEnvRemote )
131 if ( m_pContext )
133 m_pContext->aBase.acquire( &m_pContext->aBase );
135 if( m_pTid )
136 rtl_byte_sequence_acquire( pTid );
139 Job::~Job()
141 if( m_pTid )
142 rtl_byte_sequence_release( m_pTid );
143 if ( m_pContext )
145 m_pContext->aBase.release( &m_pContext->aBase );
152 //--------------------------------------------------------------------------------------
153 sal_Bool ClientJob::extract( )
155 sal_Bool bReturn = sal_True;
156 //-------------------------------
157 // Handle the reply, unpack data
158 //-------------------------------
159 if( m_bExceptionOccured )
161 bReturn = m_pUnmarshal->unpackAny( *m_ppException );
163 else
165 //---------------------------------
166 // alles ist gut
167 //---------------------------------
168 if( m_pMethodType )
170 if( m_pMethodType->pReturnTypeRef->eTypeClass != typelib_TypeClass_VOID )
172 typelib_TypeDescription *pType = 0;
173 TYPELIB_DANGER_GET( &pType , m_pMethodType->pReturnTypeRef );
174 bReturn = m_pUnmarshal->unpack( m_pReturn , pType ) && bReturn;
175 TYPELIB_DANGER_RELEASE( pType );
178 // out parameters
179 sal_Int32 i;
180 for( i = 0 ; i < m_pMethodType->nParams ; i ++ )
182 if( m_pMethodType->pParams[i].bOut )
184 typelib_TypeDescription *pType = 0;
185 TYPELIB_DANGER_GET( &pType , m_pMethodType->pParams[i].pTypeRef );
186 if( m_pMethodType->pParams[i].bIn )
188 uno_destructData( m_ppArgs[i] , pType , ::bridges_remote::remote_release );
190 bReturn = m_pUnmarshal->unpack( m_ppArgs[i] , pType ) && bReturn;
191 TYPELIB_DANGER_RELEASE( pType );
195 else if( m_pAttributeType && m_pReturn )
197 typelib_TypeDescription *pType = 0;
198 TYPELIB_DANGER_GET( &pType , m_pAttributeType->pAttributeTypeRef );
199 bReturn = m_pUnmarshal->unpack( m_pReturn , pType ) && bReturn;
200 TYPELIB_DANGER_RELEASE( pType );
202 else if( m_pAttributeType && m_ppArgs )
204 // nothing to do
206 else
208 OSL_ASSERT( 0 );
211 return bReturn;
214 //-------------------------------------------------------------------------------------------
215 void ClientJob::initiate()
217 uno_threadpool_putJob( m_pBridgeImpl->m_hThreadPool, m_pTid , this, 0, sal_False);
220 //--------------------------------------------------------------------------------------------
221 sal_Bool ClientJob::pack()
223 sal_Bool bSuccess = sal_True;
224 MutexGuard guard( m_pBridgeImpl->m_marshalingMutex );
226 if( m_pMethodType &&
227 REMOTE_RELEASE_METHOD_INDEX == m_pMethodType->aBase.nPosition &&
228 ! m_pBridgeImpl->m_bDisposed &&
229 m_pBridgeImpl->m_pWriter->getIdentifier() != ::osl::Thread::getCurrentIdentifier() )
231 // all release calls are delegated to the writer thread to avoid
232 // multiple synchron calls with the same thread id and reentrant
233 // marshaling (in case during destruction of parameters a release is
234 // invoked ).
235 m_pBridgeImpl->m_pWriter->insertReleaseRemoteCall(
236 m_pOid, m_pInterfaceType->aBase.pWeakRef );
238 // No waiting, please
239 return sal_False;
241 else if ( m_pMethodType &&
242 REMOTE_RELEASE_METHOD_INDEX == m_pMethodType->aBase.nPosition &&
243 m_pBridgeImpl->m_bDisposed )
245 // no exception for release calls !
246 return sal_False;
248 else if( m_pBridgeImpl->m_bDisposed )
250 OUStringBuffer buf( 128 );
251 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "URP-Bridge: disposed" ) );
252 buf.append( m_pBridgeImpl->getErrorsAsString() );
253 prepareRuntimeExceptionClientSide( m_ppException , buf.makeStringAndClear() );
254 return sal_False;
257 // build up the flag byte
258 sal_Bool bType = sal_False, bOid = sal_False, bTid = sal_False;
259 sal_uInt8 nFlags = 0;
260 if( m_pBridgeImpl->m_lastOutType.getTypeLibType() != m_pInterfaceType->aBase.pWeakRef &&
261 ! typelib_typedescriptionreference_equals(
262 m_pBridgeImpl->m_lastOutType.getTypeLibType(), m_pInterfaceType->aBase.pWeakRef ) )
264 //new type
265 nFlags = nFlags | HDRFLAG_NEWTYPE;
266 bType = sal_True;
268 if( m_pBridgeImpl->m_lastOutOid.pData != m_pOid &&
269 rtl_ustr_compare_WithLength( m_pBridgeImpl->m_lastOutOid.pData->buffer,
270 m_pBridgeImpl->m_lastOutOid.pData->length,
271 m_pOid->buffer,
272 m_pOid->length ) )
274 //new object id
275 nFlags = nFlags | HDRFLAG_NEWOID;
276 bOid = sal_True;
278 if( m_pBridgeImpl->m_lastOutTid.getHandle() != m_pTid &&
279 !(m_pBridgeImpl->m_lastOutTid == *(ByteSequence*) &(m_pTid) ) )
281 // new threadid
282 nFlags = nFlags | HDRFLAG_NEWTID;
283 bTid = sal_True;
286 if( m_bCallingConventionForced )
288 nFlags = nFlags | HDRFLAG_MOREFLAGS;
290 #ifdef BRIDGES_URP_PROT
291 sal_Int32 nLogStart = m_pBridgeImpl->m_blockMarshaler.getPos();
292 #endif
293 // Short request headers can only handle 14-bit method IDs, so
294 // unconditionally use a long header for method IDs that are too large:
295 if( nFlags || m_nMethodIndex >= 0xC000 )
297 // the flag byte is needed + request
298 nFlags = nFlags | HDRFLAG_LONGHEADER | HDRFLAG_REQUEST; //
300 // as long as we do not have customized calls, no MOREFLAGS must be set
301 if( m_nMethodIndex >= 0x100 )
303 nFlags = nFlags | HDRFLAG_LONGMETHODID;
305 m_pBridgeImpl->m_blockMarshaler.packInt8( &nFlags );
307 if( nFlags & HDRFLAG_MOREFLAGS )
309 sal_uInt8 nMoreFlags = 0;
310 if( ! m_bOneway )
312 nMoreFlags = HDRFLAG_SYNCHRONOUS |HDRFLAG_MUSTREPLY;
314 m_pBridgeImpl->m_blockMarshaler.packInt8( &nMoreFlags );
316 if( nFlags & HDRFLAG_LONGMETHODID )
318 sal_uInt16 nMethod = (sal_uInt16 ) m_nMethodIndex;
319 m_pBridgeImpl->m_blockMarshaler.packInt16( &nMethod );
321 else
323 sal_uInt8 nMethod = (sal_uInt8) m_nMethodIndex;
324 m_pBridgeImpl->m_blockMarshaler.packInt8( &nMethod );
327 else
329 // no flag byte needed, simply marshal the method index
330 if( m_nMethodIndex >= 64 )
332 sal_uInt16 nMethod = ( sal_uInt16 ) m_nMethodIndex;
333 nMethod = nMethod | 0x4000;
334 m_pBridgeImpl->m_blockMarshaler.packInt16( &nMethod );
336 else
338 sal_uInt8 nMethod = (sal_uInt8 ) m_nMethodIndex;
339 m_pBridgeImpl->m_blockMarshaler.packInt8( &nMethod );
343 // marshal type,oid,tid
344 if( bType )
346 m_pBridgeImpl->m_lastOutType = m_pInterfaceType->aBase.pWeakRef;
347 m_pBridgeImpl->m_blockMarshaler.packType( &(m_pBridgeImpl->m_lastOutType) );
349 if( bOid )
351 m_pBridgeImpl->m_lastOutOid = *(OUString *)&m_pOid;
352 m_pBridgeImpl->m_blockMarshaler.packOid( m_pBridgeImpl->m_lastOutOid );
354 if( bTid )
356 m_pBridgeImpl->m_lastOutTid = *(ByteSequence*)&(m_pTid);
357 m_pBridgeImpl->m_blockMarshaler.packTid( m_pBridgeImpl->m_lastOutTid );
360 if ( m_pBridgeImpl->m_properties.bCurrentContext
361 && m_nMethodIndex != REMOTE_RELEASE_METHOD_INDEX
362 && m_pContext != 0 )
364 void * pCc = 0;
365 rtl::OUString aEnvName( RTL_CONSTASCII_USTRINGPARAM( "urp" ) );
366 bSuccess = bSuccess && uno_getCurrentContext(
367 &pCc, aEnvName.pData, m_pContext );
368 typelib_TypeDescription * pType = 0;
369 TYPELIB_DANGER_GET(
370 &pType, XCurrentContext::static_type().getTypeLibType() );
371 bSuccess = bSuccess && m_pBridgeImpl->m_blockMarshaler.pack(
372 &pCc, pType );
373 TYPELIB_DANGER_RELEASE( pType );
374 if ( pCc )
376 remote_Interface * p = static_cast< remote_Interface * >( pCc );
377 p->release( p );
381 // marshal arguments !
382 #ifdef BRIDGES_URP_PROT
383 sal_Int32 nLogHeader = m_pBridgeImpl->m_blockMarshaler.getPos();
384 #endif
385 if( m_pMethodType )
387 sal_Int32 i;
388 for( i = 0 ; i < m_pMethodType->nParams ; i ++ )
390 if( m_pMethodType->pParams[i].bIn )
392 typelib_TypeDescription *pType = 0;
393 TYPELIB_DANGER_GET( &pType , m_pMethodType->pParams[i].pTypeRef );
394 if( pType )
396 bSuccess =
397 bSuccess && m_pBridgeImpl->m_blockMarshaler.pack( m_ppArgs[i] , pType );
398 TYPELIB_DANGER_RELEASE( pType );
400 else
402 bSuccess = sal_False;
403 OUStringBuffer buffer( 128 );
404 buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "no typedescription available for type" ) );
405 buffer.append( m_pMethodType->pParams[i].pTypeRef->pTypeName );
406 m_pBridgeImpl->addError( buffer.makeStringAndClear() );
411 else if( m_pAttributeType && m_pReturn )
413 // nothing to do !
415 else if( m_pAttributeType && m_ppArgs )
417 typelib_TypeDescription *pType = 0;
418 TYPELIB_DANGER_GET( &pType , m_pAttributeType->pAttributeTypeRef );
419 if( pType )
421 bSuccess = bSuccess && m_pBridgeImpl->m_blockMarshaler.pack( m_ppArgs[0] , pType );
422 TYPELIB_DANGER_RELEASE( pType );
424 else
426 bSuccess = sal_False;
427 OUStringBuffer buffer( 128 );
428 buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "no typedescription available for type" ) );
429 buffer.append( m_pAttributeType->pAttributeTypeRef->pTypeName );
430 m_pBridgeImpl->addError( buffer.makeStringAndClear() );
433 else
435 OSL_ASSERT( 0 );
438 #ifdef BRIDGES_URP_PROT
439 urp_logCall( m_pBridgeImpl, m_pBridgeImpl->m_blockMarshaler.getPos() - nLogStart,
440 m_pBridgeImpl->m_blockMarshaler.getPos() - nLogHeader, ! m_bOneway,
441 m_pMethodType ? m_pMethodType->aBase.pMemberName :
442 m_pAttributeType->aBase.pMemberName );
443 #endif
445 if( bSuccess )
447 if( ! m_bOneway )
449 uno_threadpool_attach( m_pBridgeImpl->m_hThreadPool );
450 m_pBridgeImpl->m_clientJobContainer.add( *(ByteSequence*)&(m_pTid), this );
453 m_pBridgeImpl->m_nMarshaledMessages ++;
454 //---------------------------
455 // Inform the writer thread, that there is some work to do
456 //---------------------------
457 m_pBridgeImpl->m_pWriter->touch( ! m_bOneway );
459 if( m_bOneway )
461 *m_ppException = 0;
464 else
466 // Something went wrong during packing, which means, that the caches may not be in sync
467 // anymore. So we have no other choice than to dispose the environment.
468 m_pEnvRemote->dispose( m_pEnvRemote );
469 OUStringBuffer buf( 128 );
470 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Error during marshaling " ) );
471 if( m_pMethodType )
473 buf.append( m_pMethodType->aBase.aBase.pTypeName );
475 else if( m_pAttributeType )
477 buf.append( m_pAttributeType->aBase.aBase.pTypeName );
479 buf.appendAscii( "\n" );
480 buf.append( m_pBridgeImpl->getErrorsAsString() );
481 prepareRuntimeExceptionClientSide( m_ppException , buf.makeStringAndClear() );
483 return bSuccess;
484 // release the guard
487 //------------------------------------------------------------------------------------
488 void ClientJob::wait()
490 //---------------------------
491 // Wait for the reply
492 //---------------------------
493 void * pDisposeReason = 0;
495 uno_threadpool_enter(m_pBridgeImpl->m_hThreadPool, &pDisposeReason );
497 if( ! pDisposeReason )
499 // thread has been disposed !
500 // avoid leak due continous calling on a disposed reference. The
501 // reply may or may not be within the container. If the reader thread
502 // got into problems during unmarshaling the reply for this request,
503 // it won't be in the container anymore, but it is eiterway safe to call
504 // the method
505 ClientJob *pJob =
506 m_pBridgeImpl->m_clientJobContainer.remove( *(ByteSequence*) &m_pTid );
507 if( pJob != this )
509 // this is not our job, it is probably one of the callstack below, so
510 // push it back
511 m_pBridgeImpl->m_clientJobContainer.add( *(ByteSequence*) &m_pTid , pJob );
514 OUStringBuffer sMessage( 256 );
515 sMessage.appendAscii( RTL_CONSTASCII_STRINGPARAM( "URP_Bridge : disposed\n" ) );
516 sMessage.append( m_pBridgeImpl->getErrorsAsString() );
517 prepareRuntimeExceptionClientSide( m_ppException, sMessage.makeStringAndClear() );
518 m_bExceptionOccured = sal_True;
520 else
522 OSL_ASSERT( pDisposeReason == (void*)this );
524 if( !m_bExceptionOccured )
526 *m_ppException = 0;
528 uno_threadpool_detach( m_pBridgeImpl->m_hThreadPool );
531 //------------------------------------------------------------------------------------
532 // ServerMultiJob
533 //------------------------------------------------------------------------------------
534 ServerMultiJob::ServerMultiJob(
535 uno_Environment *pEnvRemote,
536 remote_Context *pContext,
537 sal_Sequence *pTid,
538 struct urp_BridgeImpl *pBridgeImpl,
539 Unmarshal *pUnmarshal,
540 sal_Int32 nMaxMessages )
541 : Job( pEnvRemote, pContext, pTid, pBridgeImpl, pUnmarshal )
542 , m_pEnvRemote( pEnvRemote )
543 , m_nCalls( 0 )
544 , m_nMaxMessages( nMaxMessages )
545 , m_nCurrentMemPosition( 0 )
547 m_pEnvRemote->acquire( m_pEnvRemote );
548 m_nCurrentMemSize = MULTIJOB_STANDARD_MEMORY_SIZE + m_nMaxMessages * (
549 MULTIJOB_PER_CALL_MEMORY_SIZE + sizeof(ServerJobEntry) + sizeof(MemberTypeInfo) );
550 m_pCurrentMem = ( sal_Int8 * ) rtl_allocateMemory( m_nCurrentMemSize );
551 m_aEntries = ( ServerJobEntry * ) getHeap( m_nMaxMessages * sizeof( ServerJobEntry ) );
552 m_aTypeInfo = ( MemberTypeInfo * ) getHeap( m_nMaxMessages * sizeof( MemberTypeInfo ) );
555 ServerMultiJob::~ServerMultiJob()
557 sal_Int32 i;
558 for( i = 0 ; i < m_nCalls ; i ++ )
560 struct MemberTypeInfo *const pMTI = &( m_aTypeInfo[i] );
561 struct ServerJobEntry *const pSJE = &( m_aEntries[i] );
563 if( pSJE->m_pRemoteI )
564 pSJE->m_pRemoteI->release( pSJE->m_pRemoteI );
566 if( pSJE->m_pOid )
567 rtl_uString_release( pSJE->m_pOid );
569 if( pSJE->m_pInterfaceTypeRef )
570 typelib_typedescriptionreference_release( pSJE->m_pInterfaceTypeRef );
572 if( pMTI->m_pInterfaceType )
573 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription *)pMTI->m_pInterfaceType );
575 for( sal_Int32 iArgs = 0 ; iArgs < pMTI->m_nArgCount ; iArgs ++ )
577 if( pMTI->m_ppArgType[iArgs] )
578 TYPELIB_DANGER_RELEASE( pMTI->m_ppArgType [iArgs] );
580 if( pMTI->m_pReturnType )
581 TYPELIB_DANGER_RELEASE( pMTI->m_pReturnType );
583 if( pMTI->m_pMethodType )
584 typelib_typedescription_release( (typelib_TypeDescription*)pMTI->m_pMethodType );
585 if( pMTI->m_pAttributeType )
586 typelib_typedescription_release( (typelib_TypeDescription*)pMTI->m_pAttributeType );
589 rtl_freeMemory( m_pCurrentMem );
590 for( list< sal_Int8 *>::iterator ii = m_lstMem.begin() ; ii != m_lstMem.end() ; ++ii )
591 rtl_freeMemory( *ii );
593 if( m_pEnvRemote )
594 m_pEnvRemote->release( m_pEnvRemote );
597 //-------------------------------------------------------------------------------------
598 void ServerMultiJob::execute()
600 Reference< XCurrentContext > xOldCc;
601 bool bHasOldCc = false;
602 for( sal_Int32 i = 0; i < m_nCalls ; i ++ )
604 struct MemberTypeInfo * const pMTI = &( m_aTypeInfo[i] );
605 struct ServerJobEntry * const pSJE = &( m_aEntries[i] );
607 if ( pSJE->m_bHasCurrentContext )
609 if ( !bHasOldCc )
611 xOldCc = com::sun::star::uno::getCurrentContext();
612 bHasOldCc = true;
614 rtl::OUString aEnvName( RTL_CONSTASCII_USTRINGPARAM( "urp" ) );
615 if ( !uno_setCurrentContext(
616 pSJE->m_pCurrentContext, aEnvName.pData, m_pContext ) )
618 throw RuntimeException(
619 rtl::OUString(
620 RTL_CONSTASCII_USTRINGPARAM(
621 "fatal: uno_setCurrentContext failed" ) ),
622 Reference< XInterface >() );
624 if ( pSJE->m_pCurrentContext )
626 pSJE->m_pCurrentContext->release( pSJE->m_pCurrentContext );
630 if( ! pSJE->m_pRemoteI )
632 // -------------------
633 // Initial object ?
634 // ------------------
635 // be robust : Sending a release on a not constructed object
636 // provokes an segfault. Make sure, the call
637 // is not a release call.
638 remote_Context *pRemoteC = ((remote_Context*)m_pEnvRemote->pContext);
640 if( ! pMTI->m_bIsReleaseCall && pRemoteC->m_pInstanceProvider )
642 pSJE->m_pException = &(pSJE->m_exception);
644 pRemoteC->m_pInstanceProvider->getInstance(
645 pRemoteC->m_pInstanceProvider,
646 m_pEnvRemote,
647 &(pSJE->m_pRemoteI),
648 pSJE->m_pOid,
649 pMTI->m_pInterfaceType,
650 &(pSJE->m_pException));
652 else
654 prepareRuntimeException(
655 OUString( RTL_CONSTASCII_USTRINGPARAM( "urp: No instance provider set")),i);
659 if( pSJE->m_pException )
661 // errors during extracting, do nothing
663 else if( ! pSJE->m_pRemoteI )
665 // May only occur during the queryInterface call on the initial object !!!
666 // construct the return value
667 uno_type_any_construct( (uno_Any*) pSJE->m_pReturn , 0 , 0 , 0 );
669 else
671 pSJE->m_pException = &(pSJE->m_exception );
673 if( pMTI->m_bIsReleaseCall )
675 pSJE->m_pRemoteI->release( pSJE->m_pRemoteI );
676 pSJE->m_pException = 0;
678 else
680 pSJE->m_pRemoteI->pDispatcher(
681 pSJE->m_pRemoteI,
682 pMTI->m_pMethodType ? (typelib_TypeDescription*) pMTI->m_pMethodType :
683 (typelib_TypeDescription*) pMTI->m_pAttributeType,
684 pSJE->m_pReturn,
685 pSJE->m_ppArgs,
686 &(pSJE->m_pException) );
689 if( pSJE->m_pRemoteI )
692 Do the release here, in case of ForceSynchronous=1, calls
693 originated by the destructor of an UNO object must be sent BEFORE the
694 release returns ( otherwise we don't own the thread anymore ! )
696 pSJE->m_pRemoteI->release( pSJE->m_pRemoteI );
697 pSJE->m_pRemoteI = 0;
700 // now destruct parameters and marshal replies
701 // Note : when call is synchron => m_nCalls == 1
702 if( pMTI->m_bIsOneway )
704 // Oneway call, destruct in parameters
705 for( sal_Int32 j = 0 ; j < pMTI->m_pMethodType->nParams ; j ++ )
707 // usually all parameters must be in parameters, but to be robust ...
708 if( pMTI->m_pbIsIn[j] && !cppu_isSimpleType( pMTI->m_ppArgType[j] ) )
710 uno_destructData( pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] , 0 );
714 if( pSJE->m_pException )
716 uno_any_destruct( pSJE->m_pException, ::bridges_remote::remote_release );
720 else
722 // synchron, get the mutex to marshal reply and send immeadiatly
723 MutexGuard guard( m_pBridgeImpl->m_marshalingMutex );
725 sal_Bool bTid = sal_False;
726 sal_uInt8 nFlags = HDRFLAG_LONGHEADER;
727 ByteSequence tid = m_pTid;
728 if( !( tid == m_pBridgeImpl->m_lastOutTid ) || pSJE->m_bIgnoreCache )
730 // new threadid
731 nFlags = nFlags | HDRFLAG_NEWTID;
732 bTid = sal_True;
735 if( pSJE->m_pException )
737 nFlags = nFlags | HDRFLAG_EXCEPTION;
739 #ifdef BRIDGES_URP_PROT
740 sal_Int32 nLogStart = m_pBridgeImpl->m_blockMarshaler.getPos();
741 #endif
742 m_pBridgeImpl->m_blockMarshaler.packInt8( &nFlags );
744 if( bTid )
746 if( ! pSJE->m_bIgnoreCache )
748 m_pBridgeImpl->m_lastOutTid = tid;
750 m_pBridgeImpl->m_blockMarshaler.packTid( tid , pSJE->m_bIgnoreCache );
753 #ifdef BRIDGES_URP_PROT
754 sal_Int32 nLogHeader = m_pBridgeImpl->m_blockMarshaler.getPos();
755 #endif
757 if( pSJE->m_pException )
759 //--------------------
760 // an exception was thrown
761 //--------------------
762 m_pBridgeImpl->m_blockMarshaler.packAny( &(pSJE->m_exception) );
763 uno_any_destruct( &(pSJE->m_exception) , ::bridges_remote::remote_release );
765 // destroy in parameters
766 for( sal_Int32 j = 0 ; j < pMTI->m_nArgCount ; j ++ )
768 if( pMTI->m_pbIsIn[j] && ! cppu_isSimpleType( pMTI->m_ppArgType[j] ))
770 uno_destructData( pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] ,
771 ::bridges_remote::remote_release );
775 else
777 //---------------------------
778 // alles ist gut ...
779 //--------------------------
780 if( pMTI->m_pReturnType )
782 m_pBridgeImpl->m_blockMarshaler.pack(
783 pSJE->m_pReturn, pMTI->m_pReturnType );
784 if( ! cppu_isSimpleType( pMTI->m_pReturnType ) )
786 uno_destructData( pSJE->m_pReturn , pMTI->m_pReturnType ,
787 ::bridges_remote::remote_release );
790 for( sal_Int32 j = 0 ; j < pMTI->m_nArgCount ; j ++ )
792 if( pMTI->m_pbIsOut[j] )
794 m_pBridgeImpl->m_blockMarshaler.pack(
795 pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] );
797 if( ! cppu_isSimpleType( pMTI->m_ppArgType[j] ) )
799 uno_destructData( pSJE->m_ppArgs[j], pMTI->m_ppArgType[j] ,
800 ::bridges_remote::remote_release );
805 #ifdef BRIDGES_URP_PROT
807 typelib_InterfaceMemberTypeDescription *pMemberType =
808 pMTI->m_pMethodType ?
809 (typelib_InterfaceMemberTypeDescription*)pMTI->m_pMethodType :
810 (typelib_InterfaceMemberTypeDescription*)pMTI->m_pAttributeType;
812 urp_logReplying( m_pBridgeImpl ,
813 m_pBridgeImpl->m_blockMarshaler.getPos() - nLogStart,
814 m_pBridgeImpl->m_blockMarshaler.getPos() - nLogHeader,
815 pMemberType->pMemberName );
817 #endif
819 m_pBridgeImpl->m_nMarshaledMessages ++;
820 // put it on the wire
821 m_pBridgeImpl->m_pWriter->touch( sal_True );
822 } // MutexGuard marshalingMutex
824 if ( bHasOldCc )
826 if ( !com::sun::star::uno::setCurrentContext( xOldCc ) )
828 throw RuntimeException(
829 rtl::OUString(
830 RTL_CONSTASCII_USTRINGPARAM(
831 "fatal: com::sun::star::uno::setCurrentContext"
832 " failed" ) ),
833 Reference< XInterface >() );
838 //-------------------------------------------------------------------------------------
839 void ServerMultiJob::prepareRuntimeException( const OUString & sMessage , sal_Int32 nCall )
841 // -------------------------------
842 // Construct the DisposedException
843 // -------------------------------
844 com::sun::star::lang::DisposedException exception( sMessage , Reference< XInterface > () );
845 Type type = getCppuType( &exception );
846 if( !isDisposedExceptionDescriptionAvail( type ) )
848 // if it is not available (probably missing type library),
849 // then we are satisfied with throwing a normal runtime exception,
850 // for which cppu provides a static description
851 type = getCppuType( ( RuntimeException * ) 0 );
854 m_aEntries[nCall].m_pException = &(m_aEntries[nCall].m_exception);
855 uno_type_any_construct( m_aEntries[nCall].m_pException , &exception , type.getTypeLibType() , 0 );
858 //-------------------------------------------------------------------------------------
859 void ServerMultiJob::initiate()
861 uno_threadpool_putJob(
862 m_pBridgeImpl->m_hThreadPool,
863 m_pTid,
864 this,
865 doit,
866 m_aTypeInfo[0].m_bIsOneway );
870 //-------------------------------------------------------------------------------------
871 sal_Bool ServerMultiJob::extract()
873 sal_Bool bContinue = sal_True;
874 struct MemberTypeInfo * const pMTI = &(m_aTypeInfo[m_nCalls]);
875 struct ServerJobEntry * const pSJE = &(m_aEntries[m_nCalls]);
877 pSJE->m_pException = 0;
878 pSJE->m_ppArgs = 0;
879 pSJE->m_pReturn = 0;
880 pMTI->m_pReturnType = 0;
882 if( pMTI->m_nArgCount )
884 pMTI->m_ppArgType =
885 ( typelib_TypeDescription ** ) getHeap( sizeof(void*) * pMTI->m_nArgCount );
886 pSJE->m_ppArgs = (void**) getHeap( sizeof( void * ) * pMTI->m_nArgCount );
887 pMTI->m_pbIsIn = (sal_Bool *) getHeap( sizeof( sal_Bool ) * pMTI->m_nArgCount );
888 pMTI->m_pbIsOut = (sal_Bool *) getHeap( sizeof( sal_Bool ) * pMTI->m_nArgCount );
890 if( pMTI->m_pMethodType &&
891 pMTI->m_pMethodType->pReturnTypeRef->eTypeClass != typelib_TypeClass_VOID )
893 TYPELIB_DANGER_GET( &(pMTI->m_pReturnType), pMTI->m_pMethodType->pReturnTypeRef );
895 else if( pMTI->m_pAttributeType && ! pMTI->m_nArgCount )
897 TYPELIB_DANGER_GET( &(pMTI->m_pReturnType) , pMTI->m_pAttributeType->pAttributeTypeRef );
900 // normal method
901 if( pMTI->m_pMethodType )
903 for( sal_Int32 i = 0 ; i < pMTI->m_nArgCount ; i ++ )
905 pMTI->m_ppArgType[i] = 0;
906 TYPELIB_DANGER_GET( & ( pMTI->m_ppArgType[i] ) , pMTI->m_pMethodType->pParams[i].pTypeRef);
907 pMTI->m_pbIsIn[i] = pMTI->m_pMethodType->pParams[i].bIn;
908 pMTI->m_pbIsOut[i] = pMTI->m_pMethodType->pParams[i].bOut;
910 pSJE->m_ppArgs[i] = getHeap( pMTI->m_ppArgType[i]->nSize );
911 if( pMTI->m_pbIsIn[i] )
913 // everything needs to be constructed
914 bContinue = m_pUnmarshal->unpack(
915 pSJE->m_ppArgs[i], pMTI->m_ppArgType[i] ) && bContinue;
919 else if( pMTI->m_nArgCount )
921 // set attribut
922 pMTI->m_ppArgType[0] = 0;
923 pMTI->m_pbIsIn[0] = sal_True;
924 pMTI->m_pbIsOut[0] = sal_False;
925 TYPELIB_DANGER_GET(
926 & ( pMTI->m_ppArgType[0] ) , pMTI->m_pAttributeType->pAttributeTypeRef );
927 pSJE->m_ppArgs[0] = getHeap( pMTI->m_ppArgType[0]->nSize );
928 bContinue = m_pUnmarshal->unpack(
929 pSJE->m_ppArgs[0], pMTI->m_ppArgType[0] ) && bContinue;
932 if( pMTI->m_pReturnType )
934 pSJE->m_pReturn = getHeap( pMTI->m_pReturnType->nSize );
937 m_nCalls ++;
938 return bContinue;