summaryrefslogtreecommitdiff
path: root/bridges/source/remote/urp/urp_job.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/remote/urp/urp_job.cxx')
-rw-r--r--bridges/source/remote/urp/urp_job.cxx942
1 files changed, 942 insertions, 0 deletions
diff --git a/bridges/source/remote/urp/urp_job.cxx b/bridges/source/remote/urp/urp_job.cxx
new file mode 100644
index 000000000000..918affdbe689
--- /dev/null
+++ b/bridges/source/remote/urp/urp_job.cxx
@@ -0,0 +1,942 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: urp_job.cxx,v $
+ * $Revision: 1.17 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+#include <string.h>
+#include <stdio.h>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+
+#include <rtl/alloc.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <uno/current_context.h>
+#include <uno/current_context.hxx>
+#include <uno/threadpool.h>
+
+#include <bridges/cpp_uno/type_misc.hxx>
+#include <bridges/remote/proxy.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/XCurrentContext.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+
+#include "urp_job.hxx"
+#include "urp_bridgeimpl.hxx"
+#include "urp_writer.hxx"
+#include "urp_dispatch.hxx"
+#include "urp_log.hxx"
+#include "urp_marshal.hxx"
+#include "urp_propertyobject.hxx"
+#include "urp_reader.hxx"
+
+using namespace ::std;
+using namespace ::rtl;
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+
+using namespace bridges_urp;
+
+extern "C" {
+
+static void SAL_CALL doit(void * job) {
+ ServerMultiJob * p = static_cast< ServerMultiJob * >(job);
+ p->execute();
+ delete p;
+}
+
+}
+
+namespace bridges_urp
+{
+ static sal_Bool isDisposedExceptionDescriptionAvail( const Type &type )
+ {
+ static sal_Bool bInit;
+ static sal_Bool bReturn;
+ // we don't care for thread safety here, as both threads must come
+ // to the same result
+ if( ! bInit )
+ {
+ typelib_TypeDescription *pTD = 0;
+ typelib_typedescriptionreference_getDescription( & pTD, type.getTypeLibType() );
+ if( pTD )
+ {
+ bReturn = sal_True;
+ typelib_typedescription_release( pTD );
+ }
+ else
+ {
+ bReturn = sal_False;
+ }
+ bInit = sal_True;
+ }
+ return bReturn;
+ }
+
+ //--------------------------------------------------------------------------------------
+ static void prepareRuntimeExceptionClientSide( uno_Any **ppException , const OUString &s)
+ {
+ com::sun::star::lang::DisposedException exception( s , Reference< XInterface > () );
+ Type type = ::getCppuType( &exception );
+ if( !isDisposedExceptionDescriptionAvail( type ) )
+ {
+ // if it is not available (probably missing type library),
+ // then we are satisfied with throwing a normal runtime exception,
+ // for which cppu provides a static description
+ type = getCppuType( ( RuntimeException * ) 0 );
+ }
+ uno_type_any_construct( *ppException , &exception , type.getTypeLibType() , 0 );
+ }
+
+
+ Job::Job( uno_Environment *pEnvRemote,
+ remote_Context *pContext,
+ sal_Sequence *pTid,
+ struct urp_BridgeImpl *pBridgeImpl,
+ Unmarshal *pUnmarshal )
+ : m_pContext( pContext )
+ , m_pUnmarshal( pUnmarshal )
+ , m_pBridgeImpl( pBridgeImpl )
+ , m_pTid( pTid )
+ , m_counter( pEnvRemote )
+ {
+ if ( m_pContext )
+ {
+ m_pContext->aBase.acquire( &m_pContext->aBase );
+ }
+ if( m_pTid )
+ rtl_byte_sequence_acquire( pTid );
+ }
+
+ Job::~Job()
+ {
+ if( m_pTid )
+ rtl_byte_sequence_release( m_pTid );
+ if ( m_pContext )
+ {
+ m_pContext->aBase.release( &m_pContext->aBase );
+ }
+ }
+
+
+
+
+ //--------------------------------------------------------------------------------------
+ sal_Bool ClientJob::extract( )
+ {
+ sal_Bool bReturn = sal_True;
+ //-------------------------------
+ // Handle the reply, unpack data
+ //-------------------------------
+ if( m_bExceptionOccured )
+ {
+ bReturn = m_pUnmarshal->unpackAny( *m_ppException );
+ }
+ else
+ {
+ //---------------------------------
+ // alles ist gut
+ //---------------------------------
+ if( m_pMethodType )
+ {
+ if( m_pMethodType->pReturnTypeRef->eTypeClass != typelib_TypeClass_VOID )
+ {
+ typelib_TypeDescription *pType = 0;
+ TYPELIB_DANGER_GET( &pType , m_pMethodType->pReturnTypeRef );
+ bReturn = m_pUnmarshal->unpack( m_pReturn , pType ) && bReturn;
+ TYPELIB_DANGER_RELEASE( pType );
+ }
+
+ // out parameters
+ sal_Int32 i;
+ for( i = 0 ; i < m_pMethodType->nParams ; i ++ )
+ {
+ if( m_pMethodType->pParams[i].bOut )
+ {
+ typelib_TypeDescription *pType = 0;
+ TYPELIB_DANGER_GET( &pType , m_pMethodType->pParams[i].pTypeRef );
+ if( m_pMethodType->pParams[i].bIn )
+ {
+ uno_destructData( m_ppArgs[i] , pType , ::bridges_remote::remote_release );
+ }
+ bReturn = m_pUnmarshal->unpack( m_ppArgs[i] , pType ) && bReturn;
+ TYPELIB_DANGER_RELEASE( pType );
+ }
+ }
+ }
+ else if( m_pAttributeType && m_pReturn )
+ {
+ typelib_TypeDescription *pType = 0;
+ TYPELIB_DANGER_GET( &pType , m_pAttributeType->pAttributeTypeRef );
+ bReturn = m_pUnmarshal->unpack( m_pReturn , pType ) && bReturn;
+ TYPELIB_DANGER_RELEASE( pType );
+ }
+ else if( m_pAttributeType && m_ppArgs )
+ {
+ // nothing to do
+ }
+ else
+ {
+ OSL_ASSERT( 0 );
+ }
+ }
+ return bReturn;
+ }
+
+ //-------------------------------------------------------------------------------------------
+ void ClientJob::initiate()
+ {
+ uno_threadpool_putJob( m_pBridgeImpl->m_hThreadPool, m_pTid , this, 0, sal_False);
+ }
+
+ //--------------------------------------------------------------------------------------------
+ sal_Bool ClientJob::pack()
+ {
+ sal_Bool bSuccess = sal_True;
+ MutexGuard guard( m_pBridgeImpl->m_marshalingMutex );
+
+ if( m_pMethodType &&
+ REMOTE_RELEASE_METHOD_INDEX == m_pMethodType->aBase.nPosition &&
+ ! m_pBridgeImpl->m_bDisposed &&
+ m_pBridgeImpl->m_pWriter->getIdentifier() != ::osl::Thread::getCurrentIdentifier() )
+ {
+ // all release calls are delegated to the writer thread to avoid
+ // multiple synchron calls with the same thread id and reentrant
+ // marshaling (in case during destruction of parameters a release is
+ // invoked ).
+ m_pBridgeImpl->m_pWriter->insertReleaseRemoteCall(
+ m_pOid, m_pInterfaceType->aBase.pWeakRef );
+
+ // No waiting, please
+ return sal_False;
+ }
+ else if ( m_pMethodType &&
+ REMOTE_RELEASE_METHOD_INDEX == m_pMethodType->aBase.nPosition &&
+ m_pBridgeImpl->m_bDisposed )
+ {
+ // no exception for release calls !
+ return sal_False;
+ }
+ else if( m_pBridgeImpl->m_bDisposed )
+ {
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "URP-Bridge: disposed" ) );
+ buf.append( m_pBridgeImpl->getErrorsAsString() );
+ prepareRuntimeExceptionClientSide( m_ppException , buf.makeStringAndClear() );
+ return sal_False;
+ }
+
+ // build up the flag byte
+ sal_Bool bType = sal_False, bOid = sal_False, bTid = sal_False;
+ sal_uInt8 nFlags = 0;
+ if( m_pBridgeImpl->m_lastOutType.getTypeLibType() != m_pInterfaceType->aBase.pWeakRef &&
+ ! typelib_typedescriptionreference_equals(
+ m_pBridgeImpl->m_lastOutType.getTypeLibType(), m_pInterfaceType->aBase.pWeakRef ) )
+ {
+ //new type
+ nFlags = nFlags | HDRFLAG_NEWTYPE;
+ bType = sal_True;
+ }
+ if( m_pBridgeImpl->m_lastOutOid.pData != m_pOid &&
+ rtl_ustr_compare_WithLength( m_pBridgeImpl->m_lastOutOid.pData->buffer,
+ m_pBridgeImpl->m_lastOutOid.pData->length,
+ m_pOid->buffer,
+ m_pOid->length ) )
+ {
+ //new object id
+ nFlags = nFlags | HDRFLAG_NEWOID;
+ bOid = sal_True;
+ }
+ if( m_pBridgeImpl->m_lastOutTid.getHandle() != m_pTid &&
+ !(m_pBridgeImpl->m_lastOutTid == *(ByteSequence*) &(m_pTid) ) )
+ {
+ // new threadid
+ nFlags = nFlags | HDRFLAG_NEWTID;
+ bTid = sal_True;
+ }
+
+ if( m_bCallingConventionForced )
+ {
+ nFlags = nFlags | HDRFLAG_MOREFLAGS;
+ }
+#ifdef BRIDGES_URP_PROT
+ sal_Int32 nLogStart = m_pBridgeImpl->m_blockMarshaler.getPos();
+#endif
+ // Short request headers can only handle 14-bit method IDs, so
+ // unconditionally use a long header for method IDs that are too large:
+ if( nFlags || m_nMethodIndex >= 0xC000 )
+ {
+ // the flag byte is needed + request
+ nFlags = nFlags | HDRFLAG_LONGHEADER | HDRFLAG_REQUEST; //
+
+ // as long as we do not have customized calls, no MOREFLAGS must be set
+ if( m_nMethodIndex >= 0x100 )
+ {
+ nFlags = nFlags | HDRFLAG_LONGMETHODID;
+ }
+ m_pBridgeImpl->m_blockMarshaler.packInt8( &nFlags );
+
+ if( nFlags & HDRFLAG_MOREFLAGS )
+ {
+ sal_uInt8 nMoreFlags = 0;
+ if( ! m_bOneway )
+ {
+ nMoreFlags = HDRFLAG_SYNCHRONOUS |HDRFLAG_MUSTREPLY;
+ }
+ m_pBridgeImpl->m_blockMarshaler.packInt8( &nMoreFlags );
+ }
+ if( nFlags & HDRFLAG_LONGMETHODID )
+ {
+ sal_uInt16 nMethod = (sal_uInt16 ) m_nMethodIndex;
+ m_pBridgeImpl->m_blockMarshaler.packInt16( &nMethod );
+ }
+ else
+ {
+ sal_uInt8 nMethod = (sal_uInt8) m_nMethodIndex;
+ m_pBridgeImpl->m_blockMarshaler.packInt8( &nMethod );
+ }
+ }
+ else
+ {
+ // no flag byte needed, simply marshal the method index
+ if( m_nMethodIndex >= 64 )
+ {
+ sal_uInt16 nMethod = ( sal_uInt16 ) m_nMethodIndex;
+ nMethod = nMethod | 0x4000;
+ m_pBridgeImpl->m_blockMarshaler.packInt16( &nMethod );
+ }
+ else
+ {
+ sal_uInt8 nMethod = (sal_uInt8 ) m_nMethodIndex;
+ m_pBridgeImpl->m_blockMarshaler.packInt8( &nMethod );
+ }
+ }
+
+ // marshal type,oid,tid
+ if( bType )
+ {
+ m_pBridgeImpl->m_lastOutType = m_pInterfaceType->aBase.pWeakRef;
+ m_pBridgeImpl->m_blockMarshaler.packType( &(m_pBridgeImpl->m_lastOutType) );
+ }
+ if( bOid )
+ {
+ m_pBridgeImpl->m_lastOutOid = *(OUString *)&m_pOid;
+ m_pBridgeImpl->m_blockMarshaler.packOid( m_pBridgeImpl->m_lastOutOid );
+ }
+ if( bTid )
+ {
+ m_pBridgeImpl->m_lastOutTid = *(ByteSequence*)&(m_pTid);
+ m_pBridgeImpl->m_blockMarshaler.packTid( m_pBridgeImpl->m_lastOutTid );
+ }
+
+ if ( m_pBridgeImpl->m_properties.bCurrentContext
+ && m_nMethodIndex != REMOTE_RELEASE_METHOD_INDEX
+ && m_pContext != 0 )
+ {
+ void * pCc = 0;
+ rtl::OUString aEnvName( RTL_CONSTASCII_USTRINGPARAM( "urp" ) );
+ bSuccess = bSuccess && uno_getCurrentContext(
+ &pCc, aEnvName.pData, m_pContext );
+ typelib_TypeDescription * pType = 0;
+ TYPELIB_DANGER_GET(
+ &pType, XCurrentContext::static_type().getTypeLibType() );
+ bSuccess = bSuccess && m_pBridgeImpl->m_blockMarshaler.pack(
+ &pCc, pType );
+ TYPELIB_DANGER_RELEASE( pType );
+ if ( pCc )
+ {
+ remote_Interface * p = static_cast< remote_Interface * >( pCc );
+ p->release( p );
+ }
+ }
+
+ // marshal arguments !
+#ifdef BRIDGES_URP_PROT
+ sal_Int32 nLogHeader = m_pBridgeImpl->m_blockMarshaler.getPos();
+#endif
+ if( m_pMethodType )
+ {
+ sal_Int32 i;
+ for( i = 0 ; i < m_pMethodType->nParams ; i ++ )
+ {
+ if( m_pMethodType->pParams[i].bIn )
+ {
+ typelib_TypeDescription *pType = 0;
+ TYPELIB_DANGER_GET( &pType , m_pMethodType->pParams[i].pTypeRef );
+ if( pType )
+ {
+ bSuccess =
+ bSuccess && m_pBridgeImpl->m_blockMarshaler.pack( m_ppArgs[i] , pType );
+ TYPELIB_DANGER_RELEASE( pType );
+ }
+ else
+ {
+ bSuccess = sal_False;
+ OUStringBuffer buffer( 128 );
+ buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "no typedescription available for type" ) );
+ buffer.append( m_pMethodType->pParams[i].pTypeRef->pTypeName );
+ m_pBridgeImpl->addError( buffer.makeStringAndClear() );
+ }
+ }
+ }
+ }
+ else if( m_pAttributeType && m_pReturn )
+ {
+ // nothing to do !
+ }
+ else if( m_pAttributeType && m_ppArgs )
+ {
+ typelib_TypeDescription *pType = 0;
+ TYPELIB_DANGER_GET( &pType , m_pAttributeType->pAttributeTypeRef );
+ if( pType )
+ {
+ bSuccess = bSuccess && m_pBridgeImpl->m_blockMarshaler.pack( m_ppArgs[0] , pType );
+ TYPELIB_DANGER_RELEASE( pType );
+ }
+ else
+ {
+ bSuccess = sal_False;
+ OUStringBuffer buffer( 128 );
+ buffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "no typedescription available for type" ) );
+ buffer.append( m_pAttributeType->pAttributeTypeRef->pTypeName );
+ m_pBridgeImpl->addError( buffer.makeStringAndClear() );
+ }
+ }
+ else
+ {
+ OSL_ASSERT( 0 );
+ }
+
+#ifdef BRIDGES_URP_PROT
+ urp_logCall( m_pBridgeImpl, m_pBridgeImpl->m_blockMarshaler.getPos() - nLogStart,
+ m_pBridgeImpl->m_blockMarshaler.getPos() - nLogHeader, ! m_bOneway,
+ m_pMethodType ? m_pMethodType->aBase.pMemberName :
+ m_pAttributeType->aBase.pMemberName );
+#endif
+
+ if( bSuccess )
+ {
+ if( ! m_bOneway )
+ {
+ uno_threadpool_attach( m_pBridgeImpl->m_hThreadPool );
+ m_pBridgeImpl->m_clientJobContainer.add( *(ByteSequence*)&(m_pTid), this );
+ }
+
+ m_pBridgeImpl->m_nMarshaledMessages ++;
+ //---------------------------
+ // Inform the writer thread, that there is some work to do
+ //---------------------------
+ m_pBridgeImpl->m_pWriter->touch( ! m_bOneway );
+
+ if( m_bOneway )
+ {
+ *m_ppException = 0;
+ }
+ }
+ else
+ {
+ // Something went wrong during packing, which means, that the caches may not be in sync
+ // anymore. So we have no other choice than to dispose the environment.
+ m_pEnvRemote->dispose( m_pEnvRemote );
+ OUStringBuffer buf( 128 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Error during marshaling " ) );
+ if( m_pMethodType )
+ {
+ buf.append( m_pMethodType->aBase.aBase.pTypeName );
+ }
+ else if( m_pAttributeType )
+ {
+ buf.append( m_pAttributeType->aBase.aBase.pTypeName );
+ }
+ buf.appendAscii( "\n" );
+ buf.append( m_pBridgeImpl->getErrorsAsString() );
+ prepareRuntimeExceptionClientSide( m_ppException , buf.makeStringAndClear() );
+ }
+ return bSuccess;
+ // release the guard
+ }
+
+ //------------------------------------------------------------------------------------
+ void ClientJob::wait()
+ {
+ //---------------------------
+ // Wait for the reply
+ //---------------------------
+ void * pDisposeReason = 0;
+
+ uno_threadpool_enter(m_pBridgeImpl->m_hThreadPool, &pDisposeReason );
+
+ if( ! pDisposeReason )
+ {
+ // thread has been disposed !
+ // avoid leak due continous calling on a disposed reference. The
+ // reply may or may not be within the container. If the reader thread
+ // got into problems during unmarshaling the reply for this request,
+ // it won't be in the container anymore, but it is eiterway safe to call
+ // the method
+ ClientJob *pJob =
+ m_pBridgeImpl->m_clientJobContainer.remove( *(ByteSequence*) &m_pTid );
+ if( pJob != this )
+ {
+ // this is not our job, it is probably one of the callstack below, so
+ // push it back
+ m_pBridgeImpl->m_clientJobContainer.add( *(ByteSequence*) &m_pTid , pJob );
+ }
+
+ OUStringBuffer sMessage( 256 );
+ sMessage.appendAscii( RTL_CONSTASCII_STRINGPARAM( "URP_Bridge : disposed\n" ) );
+ sMessage.append( m_pBridgeImpl->getErrorsAsString() );
+ prepareRuntimeExceptionClientSide( m_ppException, sMessage.makeStringAndClear() );
+ m_bExceptionOccured = sal_True;
+ }
+ else
+ {
+ OSL_ASSERT( pDisposeReason == (void*)this );
+ }
+ if( !m_bExceptionOccured )
+ {
+ *m_ppException = 0;
+ }
+ uno_threadpool_detach( m_pBridgeImpl->m_hThreadPool );
+ }
+
+ //------------------------------------------------------------------------------------
+ // ServerMultiJob
+ //------------------------------------------------------------------------------------
+ ServerMultiJob::ServerMultiJob(
+ uno_Environment *pEnvRemote,
+ remote_Context *pContext,
+ sal_Sequence *pTid,
+ struct urp_BridgeImpl *pBridgeImpl,
+ Unmarshal *pUnmarshal,
+ sal_Int32 nMaxMessages )
+ : Job( pEnvRemote, pContext, pTid, pBridgeImpl, pUnmarshal )
+ , m_pEnvRemote( pEnvRemote )
+ , m_nCalls( 0 )
+ , m_nMaxMessages( nMaxMessages )
+ , m_nCurrentMemPosition( 0 )
+ {
+ m_pEnvRemote->acquire( m_pEnvRemote );
+ m_nCurrentMemSize = MULTIJOB_STANDARD_MEMORY_SIZE + m_nMaxMessages * (
+ MULTIJOB_PER_CALL_MEMORY_SIZE + sizeof(ServerJobEntry) + sizeof(MemberTypeInfo) );
+ m_pCurrentMem = ( sal_Int8 * ) rtl_allocateMemory( m_nCurrentMemSize );
+ m_aEntries = ( ServerJobEntry * ) getHeap( m_nMaxMessages * sizeof( ServerJobEntry ) );
+ m_aTypeInfo = ( MemberTypeInfo * ) getHeap( m_nMaxMessages * sizeof( MemberTypeInfo ) );
+ }
+
+ ServerMultiJob::~ServerMultiJob()
+ {
+ sal_Int32 i;
+ for( i = 0 ; i < m_nCalls ; i ++ )
+ {
+ struct MemberTypeInfo *const pMTI = &( m_aTypeInfo[i] );
+ struct ServerJobEntry *const pSJE = &( m_aEntries[i] );
+
+ if( pSJE->m_pRemoteI )
+ pSJE->m_pRemoteI->release( pSJE->m_pRemoteI );
+
+ if( pSJE->m_pOid )
+ rtl_uString_release( pSJE->m_pOid );
+
+ if( pSJE->m_pInterfaceTypeRef )
+ typelib_typedescriptionreference_release( pSJE->m_pInterfaceTypeRef );
+
+ if( pMTI->m_pInterfaceType )
+ TYPELIB_DANGER_RELEASE( (typelib_TypeDescription *)pMTI->m_pInterfaceType );
+
+ for( sal_Int32 iArgs = 0 ; iArgs < pMTI->m_nArgCount ; iArgs ++ )
+ {
+ if( pMTI->m_ppArgType[iArgs] )
+ TYPELIB_DANGER_RELEASE( pMTI->m_ppArgType [iArgs] );
+ }
+ if( pMTI->m_pReturnType )
+ TYPELIB_DANGER_RELEASE( pMTI->m_pReturnType );
+
+ if( pMTI->m_pMethodType )
+ typelib_typedescription_release( (typelib_TypeDescription*)pMTI->m_pMethodType );
+ if( pMTI->m_pAttributeType )
+ typelib_typedescription_release( (typelib_TypeDescription*)pMTI->m_pAttributeType );
+ }
+
+ rtl_freeMemory( m_pCurrentMem );
+ for( list< sal_Int8 *>::iterator ii = m_lstMem.begin() ; ii != m_lstMem.end() ; ++ii )
+ rtl_freeMemory( *ii );
+
+ if( m_pEnvRemote )
+ m_pEnvRemote->release( m_pEnvRemote );
+ }
+
+ //-------------------------------------------------------------------------------------
+ void ServerMultiJob::execute()
+ {
+ Reference< XCurrentContext > xOldCc;
+ bool bHasOldCc = false;
+ for( sal_Int32 i = 0; i < m_nCalls ; i ++ )
+ {
+ struct MemberTypeInfo * const pMTI = &( m_aTypeInfo[i] );
+ struct ServerJobEntry * const pSJE = &( m_aEntries[i] );
+
+ if ( pSJE->m_bHasCurrentContext )
+ {
+ if ( !bHasOldCc )
+ {
+ xOldCc = com::sun::star::uno::getCurrentContext();
+ bHasOldCc = true;
+ }
+ rtl::OUString aEnvName( RTL_CONSTASCII_USTRINGPARAM( "urp" ) );
+ if ( !uno_setCurrentContext(
+ pSJE->m_pCurrentContext, aEnvName.pData, m_pContext ) )
+ {
+ throw RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "fatal: uno_setCurrentContext failed" ) ),
+ Reference< XInterface >() );
+ }
+ if ( pSJE->m_pCurrentContext )
+ {
+ pSJE->m_pCurrentContext->release( pSJE->m_pCurrentContext );
+ }
+ }
+
+ if( ! pSJE->m_pRemoteI )
+ {
+ // -------------------
+ // Initial object ?
+ // ------------------
+ // be robust : Sending a release on a not constructed object
+ // provokes an segfault. Make sure, the call
+ // is not a release call.
+ remote_Context *pRemoteC = ((remote_Context*)m_pEnvRemote->pContext);
+
+ if( ! pMTI->m_bIsReleaseCall && pRemoteC->m_pInstanceProvider )
+ {
+ pSJE->m_pException = &(pSJE->m_exception);
+
+ pRemoteC->m_pInstanceProvider->getInstance(
+ pRemoteC->m_pInstanceProvider,
+ m_pEnvRemote,
+ &(pSJE->m_pRemoteI),
+ pSJE->m_pOid,
+ pMTI->m_pInterfaceType,
+ &(pSJE->m_pException));
+ }
+ else
+ {
+ prepareRuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "urp: No instance provider set")),i);
+ }
+ }
+
+ if( pSJE->m_pException )
+ {
+ // errors during extracting, do nothing
+ }
+ else if( ! pSJE->m_pRemoteI )
+ {
+ // May only occur during the queryInterface call on the initial object !!!
+ // construct the return value
+ uno_type_any_construct( (uno_Any*) pSJE->m_pReturn , 0 , 0 , 0 );
+ }
+ else
+ {
+ pSJE->m_pException = &(pSJE->m_exception );
+
+ if( pMTI->m_bIsReleaseCall )
+ {
+ pSJE->m_pRemoteI->release( pSJE->m_pRemoteI );
+ pSJE->m_pException = 0;
+ }
+ else
+ {
+ pSJE->m_pRemoteI->pDispatcher(
+ pSJE->m_pRemoteI,
+ pMTI->m_pMethodType ? (typelib_TypeDescription*) pMTI->m_pMethodType :
+ (typelib_TypeDescription*) pMTI->m_pAttributeType,
+ pSJE->m_pReturn,
+ pSJE->m_ppArgs,
+ &(pSJE->m_pException) );
+ }
+ }
+ if( pSJE->m_pRemoteI )
+ {
+ /**
+ Do the release here, in case of ForceSynchronous=1, calls
+ originated by the destructor of an UNO object must be sent BEFORE the
+ release returns ( otherwise we don't own the thread anymore ! )
+ */
+ pSJE->m_pRemoteI->release( pSJE->m_pRemoteI );
+ pSJE->m_pRemoteI = 0;
+ }
+
+ // now destruct parameters and marshal replies
+ // Note : when call is synchron => m_nCalls == 1
+ if( pMTI->m_bIsOneway )
+ {
+ // Oneway call, destruct in parameters
+ for( sal_Int32 j = 0 ; j < pMTI->m_pMethodType->nParams ; j ++ )
+ {
+ // usually all parameters must be in parameters, but to be robust ...
+ if( pMTI->m_pbIsIn[j] && !cppu_isSimpleType( pMTI->m_ppArgType[j] ) )
+ {
+ uno_destructData( pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] , 0 );
+ }
+ }
+
+ if( pSJE->m_pException )
+ {
+ uno_any_destruct( pSJE->m_pException, ::bridges_remote::remote_release );
+ }
+
+ }
+ else
+ {
+ // synchron, get the mutex to marshal reply and send immeadiatly
+ MutexGuard guard( m_pBridgeImpl->m_marshalingMutex );
+
+ sal_Bool bTid = sal_False;
+ sal_uInt8 nFlags = HDRFLAG_LONGHEADER;
+ ByteSequence tid = m_pTid;
+ if( !( tid == m_pBridgeImpl->m_lastOutTid ) || pSJE->m_bIgnoreCache )
+ {
+ // new threadid
+ nFlags = nFlags | HDRFLAG_NEWTID;
+ bTid = sal_True;
+ }
+
+ if( pSJE->m_pException )
+ {
+ nFlags = nFlags | HDRFLAG_EXCEPTION;
+ }
+#ifdef BRIDGES_URP_PROT
+ sal_Int32 nLogStart = m_pBridgeImpl->m_blockMarshaler.getPos();
+#endif
+ m_pBridgeImpl->m_blockMarshaler.packInt8( &nFlags );
+
+ if( bTid )
+ {
+ if( ! pSJE->m_bIgnoreCache )
+ {
+ m_pBridgeImpl->m_lastOutTid = tid;
+ }
+ m_pBridgeImpl->m_blockMarshaler.packTid( tid , pSJE->m_bIgnoreCache );
+ }
+
+#ifdef BRIDGES_URP_PROT
+ sal_Int32 nLogHeader = m_pBridgeImpl->m_blockMarshaler.getPos();
+#endif
+
+ if( pSJE->m_pException )
+ {
+ //--------------------
+ // an exception was thrown
+ //--------------------
+ m_pBridgeImpl->m_blockMarshaler.packAny( &(pSJE->m_exception) );
+ uno_any_destruct( &(pSJE->m_exception) , ::bridges_remote::remote_release );
+
+ // destroy in parameters
+ for( sal_Int32 j = 0 ; j < pMTI->m_nArgCount ; j ++ )
+ {
+ if( pMTI->m_pbIsIn[j] && ! cppu_isSimpleType( pMTI->m_ppArgType[j] ))
+ {
+ uno_destructData( pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] ,
+ ::bridges_remote::remote_release );
+ }
+ }
+ }
+ else
+ {
+ //---------------------------
+ // alles ist gut ...
+ //--------------------------
+ if( pMTI->m_pReturnType )
+ {
+ m_pBridgeImpl->m_blockMarshaler.pack(
+ pSJE->m_pReturn, pMTI->m_pReturnType );
+ if( ! cppu_isSimpleType( pMTI->m_pReturnType ) )
+ {
+ uno_destructData( pSJE->m_pReturn , pMTI->m_pReturnType ,
+ ::bridges_remote::remote_release );
+ }
+ }
+ for( sal_Int32 j = 0 ; j < pMTI->m_nArgCount ; j ++ )
+ {
+ if( pMTI->m_pbIsOut[j] )
+ {
+ m_pBridgeImpl->m_blockMarshaler.pack(
+ pSJE->m_ppArgs[j] , pMTI->m_ppArgType[j] );
+ }
+ if( ! cppu_isSimpleType( pMTI->m_ppArgType[j] ) )
+ {
+ uno_destructData( pSJE->m_ppArgs[j], pMTI->m_ppArgType[j] ,
+ ::bridges_remote::remote_release );
+ }
+ }
+ }
+
+#ifdef BRIDGES_URP_PROT
+ {
+ typelib_InterfaceMemberTypeDescription *pMemberType =
+ pMTI->m_pMethodType ?
+ (typelib_InterfaceMemberTypeDescription*)pMTI->m_pMethodType :
+ (typelib_InterfaceMemberTypeDescription*)pMTI->m_pAttributeType;
+
+ urp_logReplying( m_pBridgeImpl ,
+ m_pBridgeImpl->m_blockMarshaler.getPos() - nLogStart,
+ m_pBridgeImpl->m_blockMarshaler.getPos() - nLogHeader,
+ pMemberType->pMemberName );
+ }
+#endif
+
+ m_pBridgeImpl->m_nMarshaledMessages ++;
+ // put it on the wire
+ m_pBridgeImpl->m_pWriter->touch( sal_True );
+ } // MutexGuard marshalingMutex
+ }
+ if ( bHasOldCc )
+ {
+ if ( !com::sun::star::uno::setCurrentContext( xOldCc ) )
+ {
+ throw RuntimeException(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "fatal: com::sun::star::uno::setCurrentContext"
+ " failed" ) ),
+ Reference< XInterface >() );
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------
+ void ServerMultiJob::prepareRuntimeException( const OUString & sMessage , sal_Int32 nCall )
+ {
+ // -------------------------------
+ // Construct the DisposedException
+ // -------------------------------
+ com::sun::star::lang::DisposedException exception( sMessage , Reference< XInterface > () );
+ Type type = getCppuType( &exception );
+ if( !isDisposedExceptionDescriptionAvail( type ) )
+ {
+ // if it is not available (probably missing type library),
+ // then we are satisfied with throwing a normal runtime exception,
+ // for which cppu provides a static description
+ type = getCppuType( ( RuntimeException * ) 0 );
+ }
+
+ m_aEntries[nCall].m_pException = &(m_aEntries[nCall].m_exception);
+ uno_type_any_construct( m_aEntries[nCall].m_pException , &exception , type.getTypeLibType() , 0 );
+ }
+
+ //-------------------------------------------------------------------------------------
+ void ServerMultiJob::initiate()
+ {
+ uno_threadpool_putJob(
+ m_pBridgeImpl->m_hThreadPool,
+ m_pTid,
+ this,
+ doit,
+ m_aTypeInfo[0].m_bIsOneway );
+ }
+
+
+ //-------------------------------------------------------------------------------------
+ sal_Bool ServerMultiJob::extract()
+ {
+ sal_Bool bContinue = sal_True;
+ struct MemberTypeInfo * const pMTI = &(m_aTypeInfo[m_nCalls]);
+ struct ServerJobEntry * const pSJE = &(m_aEntries[m_nCalls]);
+
+ pSJE->m_pException = 0;
+ pSJE->m_ppArgs = 0;
+ pSJE->m_pReturn = 0;
+ pMTI->m_pReturnType = 0;
+
+ if( pMTI->m_nArgCount )
+ {
+ pMTI->m_ppArgType =
+ ( typelib_TypeDescription ** ) getHeap( sizeof(void*) * pMTI->m_nArgCount );
+ pSJE->m_ppArgs = (void**) getHeap( sizeof( void * ) * pMTI->m_nArgCount );
+ pMTI->m_pbIsIn = (sal_Bool *) getHeap( sizeof( sal_Bool ) * pMTI->m_nArgCount );
+ pMTI->m_pbIsOut = (sal_Bool *) getHeap( sizeof( sal_Bool ) * pMTI->m_nArgCount );
+ }
+ if( pMTI->m_pMethodType &&
+ pMTI->m_pMethodType->pReturnTypeRef->eTypeClass != typelib_TypeClass_VOID )
+ {
+ TYPELIB_DANGER_GET( &(pMTI->m_pReturnType), pMTI->m_pMethodType->pReturnTypeRef );
+ }
+ else if( pMTI->m_pAttributeType && ! pMTI->m_nArgCount )
+ {
+ TYPELIB_DANGER_GET( &(pMTI->m_pReturnType) , pMTI->m_pAttributeType->pAttributeTypeRef );
+ }
+
+ // normal method
+ if( pMTI->m_pMethodType )
+ {
+ for( sal_Int32 i = 0 ; i < pMTI->m_nArgCount ; i ++ )
+ {
+ pMTI->m_ppArgType[i] = 0;
+ TYPELIB_DANGER_GET( & ( pMTI->m_ppArgType[i] ) , pMTI->m_pMethodType->pParams[i].pTypeRef);
+ pMTI->m_pbIsIn[i] = pMTI->m_pMethodType->pParams[i].bIn;
+ pMTI->m_pbIsOut[i] = pMTI->m_pMethodType->pParams[i].bOut;
+
+ pSJE->m_ppArgs[i] = getHeap( pMTI->m_ppArgType[i]->nSize );
+ if( pMTI->m_pbIsIn[i] )
+ {
+ // everything needs to be constructed
+ bContinue = m_pUnmarshal->unpack(
+ pSJE->m_ppArgs[i], pMTI->m_ppArgType[i] ) && bContinue;
+ }
+ }
+ }
+ else if( pMTI->m_nArgCount )
+ {
+ // set attribut
+ pMTI->m_ppArgType[0] = 0;
+ pMTI->m_pbIsIn[0] = sal_True;
+ pMTI->m_pbIsOut[0] = sal_False;
+ TYPELIB_DANGER_GET(
+ & ( pMTI->m_ppArgType[0] ) , pMTI->m_pAttributeType->pAttributeTypeRef );
+ pSJE->m_ppArgs[0] = getHeap( pMTI->m_ppArgType[0]->nSize );
+ bContinue = m_pUnmarshal->unpack(
+ pSJE->m_ppArgs[0], pMTI->m_ppArgType[0] ) && bContinue;
+ }
+
+ if( pMTI->m_pReturnType )
+ {
+ pSJE->m_pReturn = getHeap( pMTI->m_pReturnType->nSize );
+ }
+
+ m_nCalls ++;
+ return bContinue;
+ }
+}
+
+