summaryrefslogtreecommitdiff
path: root/bridges/source/remote/urp/urp_reader.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/remote/urp/urp_reader.cxx')
-rw-r--r--bridges/source/remote/urp/urp_reader.cxx832
1 files changed, 832 insertions, 0 deletions
diff --git a/bridges/source/remote/urp/urp_reader.cxx b/bridges/source/remote/urp/urp_reader.cxx
new file mode 100644
index 000000000000..fda6c5e322eb
--- /dev/null
+++ b/bridges/source/remote/urp/urp_reader.cxx
@@ -0,0 +1,832 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <bridges/remote/connection.h>
+#include <bridges/remote/counter.hxx>
+#include <bridges/remote/context.h>
+#include <bridges/remote/helper.hxx>
+
+#include <com/sun/star/uno/XCurrentContext.hpp>
+#include <uno/environment.h>
+
+#include "urp_reader.hxx"
+#include "urp_writer.hxx"
+#include "urp_dispatch.hxx"
+#include "urp_job.hxx"
+#include "urp_bridgeimpl.hxx"
+#include "urp_log.hxx"
+#include "urp_propertyobject.hxx"
+
+using namespace ::rtl;
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+
+#if OSL_DEBUG_LEVEL > 1
+static MyCounter thisCounter( "DEBUG : ReaderThread" );
+#endif
+
+namespace bridges_urp
+{
+
+ /**
+ * This callback is used to ensure, that the release call is sent for the correct type.
+ *
+ ***/
+ void SAL_CALL urp_releaseRemoteCallback (
+ remote_Interface *, rtl_uString *pOid,
+ typelib_TypeDescriptionReference *pTypeRef, uno_Environment *pEnvRemote )
+ {
+ remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
+ urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl );
+
+ pImpl->m_pWriter->insertReleaseRemoteCall( pOid , pTypeRef );
+ }
+
+
+ struct MessageFlags
+ {
+ sal_uInt16 nMethodId;
+ sal_Bool bRequest;
+ sal_Bool bType;
+ sal_Bool bOid;
+ sal_Bool bTid;
+ sal_Bool bException;
+ sal_Bool bMustReply;
+ sal_Bool bSynchronous;
+ sal_Bool bMoreFlags;
+ sal_Bool bIgnoreCache;
+ sal_Bool bBridgePropertyCall;
+ ///--------------------------
+ inline MessageFlags()
+ {
+ bTid = sal_False;
+ bOid = sal_False;
+ bType = sal_False;
+ bException = sal_False;
+ bMoreFlags = sal_False;
+ bIgnoreCache = sal_False;
+ bBridgePropertyCall = sal_False;
+ }
+ //---------------------------
+ }; // end struct MessageFlags
+
+inline sal_Bool OReaderThread::getMemberTypeDescription(
+ typelib_InterfaceAttributeTypeDescription **ppAttributeType,
+ typelib_InterfaceMethodTypeDescription **ppMethodType,
+ sal_Bool *pbIsSetter,
+ sal_uInt16 nMethodId ,
+ typelib_TypeDescriptionReference * pITypeRef )
+{
+ if( pITypeRef->eTypeClass != typelib_TypeClass_INTERFACE )
+ {
+ OUStringBuffer sMessage;
+ sMessage.appendAscii( "interface type is not of typeclass interface (" );
+ sMessage.append( (sal_Int32) pITypeRef->eTypeClass );
+ m_pBridgeImpl->addError( sMessage.makeStringAndClear() );
+ OSL_ENSURE( 0 , "type is not an interface" );
+ return sal_False;
+ }
+
+ typelib_InterfaceTypeDescription *pInterfaceType = 0;
+ TYPELIB_DANGER_GET(
+ (typelib_TypeDescription **)&pInterfaceType , pITypeRef );
+ if( ! pInterfaceType )
+ {
+ OUStringBuffer sMessage;
+ sMessage.appendAscii( "No typedescription can be retrieved for type " );
+ sMessage.append( OUString( pITypeRef->pTypeName ) );
+ m_pBridgeImpl->addError( sMessage.makeStringAndClear() );
+ OSL_ENSURE( 0 , "urp: unknown type " );
+ return sal_False;
+ }
+
+ if( ! pInterfaceType->aBase.bComplete )
+ {
+ typelib_typedescription_complete( (typelib_TypeDescription **) &pInterfaceType );
+ }
+
+ if ( nMethodId >= pInterfaceType->nMapFunctionIndexToMemberIndex )
+ {
+ OUStringBuffer sMessage;
+ sMessage.appendAscii( "vtable out of range for type " );
+ sMessage.append( OUString( pITypeRef->pTypeName ) );
+ sMessage.appendAscii( " (" );
+ sMessage.append( (sal_Int32) nMethodId );
+ sMessage.appendAscii( " )" );
+ m_pBridgeImpl->addError( sMessage.makeStringAndClear() );
+
+ OSL_ENSURE( 0 , "vtable index out of range" );
+ return sal_False;
+ }
+
+ sal_Int32 nMemberIndex = pInterfaceType->pMapFunctionIndexToMemberIndex[ nMethodId ];
+
+ if( !( pInterfaceType->nAllMembers > nMemberIndex && nMemberIndex >= 0 ) )
+ {
+ OUStringBuffer sMessage;
+ sMessage.appendAscii( "vtable out of range for type " );
+ sMessage.append( OUString( pITypeRef->pTypeName ) );
+ sMessage.appendAscii( " (" );
+ sMessage.append( (sal_Int32) nMethodId );
+ sMessage.appendAscii( " )" );
+ m_pBridgeImpl->addError( sMessage.makeStringAndClear() );
+
+ OSL_ENSURE( 0 , "vtable index out of range" );
+ return sal_False;
+ }
+
+ typelib_InterfaceMemberTypeDescription *pMemberType = 0;
+ typelib_typedescriptionreference_getDescription(
+ (typelib_TypeDescription **) &pMemberType,pInterfaceType->ppAllMembers[nMemberIndex]);
+
+ if(! pMemberType )
+ {
+ OUStringBuffer sMessage;
+ sMessage.appendAscii( "unknown method type description for type" );
+ sMessage.append( OUString( pITypeRef->pTypeName ) );
+ sMessage.appendAscii( " (" );
+ sMessage.append( (sal_Int32) nMethodId );
+ sMessage.appendAscii( " )" );
+ m_pBridgeImpl->addError( sMessage.makeStringAndClear() );
+
+ OSL_ENSURE( 0 , "unknown method type description" );
+ return sal_False;
+ }
+
+ if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pMemberType->aBase.eTypeClass )
+ {
+ // Note: pMapMemberIndexToFunctionIndex always contains the function
+ // index of the attribute getter! setter function index is getter index
+ // + 1.
+ *ppAttributeType = (typelib_InterfaceAttributeTypeDescription *) pMemberType;
+ *pbIsSetter = ! (
+ pInterfaceType->pMapMemberIndexToFunctionIndex[nMemberIndex] == nMethodId );
+ }
+ else
+ {
+ *ppMethodType = (typelib_InterfaceMethodTypeDescription *) pMemberType;
+ }
+
+ TYPELIB_DANGER_RELEASE( (typelib_TypeDescription * )pInterfaceType );
+ return sal_True;
+}
+
+OReaderThread::OReaderThread( remote_Connection *pConnection,
+ uno_Environment *pEnvRemote,
+ OWriterThread * pWriterThread ) :
+ m_pConnection( pConnection ),
+ m_pEnvRemote( pEnvRemote ),
+ m_pWriterThread( pWriterThread ),
+ m_bDestroyMyself( sal_False ),
+ m_bContinue( sal_True ),
+ m_pBridgeImpl((struct urp_BridgeImpl*)
+ ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl ),
+ m_unmarshal( m_pBridgeImpl, m_pEnvRemote, ::bridges_remote::remote_createStub )
+{
+ m_pEnvRemote->acquireWeak( m_pEnvRemote );
+ m_pConnection->acquire( m_pConnection );
+#if OSL_DEBUG_LEVEL > 1
+ thisCounter.acquire();
+#endif
+}
+
+
+OReaderThread::~OReaderThread( )
+{
+ m_pEnvRemote->releaseWeak( m_pEnvRemote );
+#if OSL_DEBUG_LEVEL > 1
+ thisCounter.release();
+#endif
+}
+
+// may only be called in the callstack of this thread !!!!!
+// run() -> dispose() -> destroyYourself()
+void OReaderThread::destroyYourself()
+{
+ m_bDestroyMyself = sal_True;
+ m_pConnection->release( m_pConnection );
+ m_pConnection = 0;
+ m_bContinue = sal_False;
+}
+
+void OReaderThread::onTerminated()
+{
+ if( m_bDestroyMyself )
+ {
+ delete this;
+ }
+}
+
+
+void OReaderThread::disposeEnvironment()
+{
+ struct remote_Context *pContext =
+ ( struct remote_Context * ) m_pEnvRemote->pContext;
+ m_bContinue = sal_False;
+ if( ! pContext->m_pBridgeImpl->m_bDisposed )
+ {
+ uno_Environment *pEnvRemote = 0;
+ m_pEnvRemote->harden( &pEnvRemote , m_pEnvRemote );
+ if( pEnvRemote )
+ {
+ pEnvRemote->dispose( m_pEnvRemote );
+ pEnvRemote->release( m_pEnvRemote );
+ }
+ else
+ {
+ // environment has been disposed eitherway !
+ }
+ }
+}
+
+inline sal_Bool OReaderThread::readBlock( sal_Int32 *pnMessageCount )
+{
+ m_unmarshal.setSize( 8 );
+ if( 8 != m_pConnection->read( m_pConnection , m_unmarshal.getBuffer(), 8 ) )
+ {
+ OUString s( RTL_CONSTASCII_USTRINGPARAM( "Unexpected connection closure" ) );
+ m_pBridgeImpl->addError( s );
+ return sal_False;
+ }
+
+ sal_Int32 nSize;
+ m_unmarshal.unpackInt32( &nSize );
+ m_unmarshal.unpackInt32( pnMessageCount );
+
+ if( nSize < 0 )
+ {
+ // buffer too big
+ // no exception can be thrown, because there is no thread id, which could be
+ // used. -> terminate !
+ OUStringBuffer s;
+ s.appendAscii( "Packet-size too big (" );
+ s.append( (sal_Int64) (sal_uInt32 ) nSize );
+ s.append( sal_Unicode( ')' ) );
+ m_pBridgeImpl->addError( s.makeStringAndClear() );
+ OSL_ENSURE( 0 , "urp bridge: Packet-size too big" );
+ return sal_False;
+ }
+
+ if( 0 == nSize )
+ {
+ // normal termination !
+ return sal_False;
+ }
+
+ // allocate the necessary memory
+ if( ! m_unmarshal.setSize( nSize ) )
+ {
+ OUStringBuffer s;
+ s.appendAscii( "Packet-size too big, couln't allocate necessary memory (" );
+ s.append( (sal_Int64) (sal_uInt32 ) nSize );
+ s.append( sal_Unicode( ')' ) );
+ m_pBridgeImpl->addError( s.makeStringAndClear() );
+ OSL_ENSURE( 0 , "urp bridge: messages size too large, terminating connection" );
+ return sal_False;
+ }
+
+ sal_Int32 nRead = m_pConnection->read( m_pConnection , m_unmarshal.getBuffer() , nSize );
+
+ if( nSize != nRead )
+ {
+ OUStringBuffer s;
+ s.appendAscii( "Unexpected connection closure, inconsistent packet (" );
+ s.append( (sal_Int64) (sal_uInt32 ) nSize );
+ s.appendAscii( " asked, " );
+ s.append( (sal_Int64) (sal_uInt32 ) nRead );
+ s.appendAscii( " got )" );
+ m_pBridgeImpl->addError( s.makeStringAndClear() );
+ // couldn't get the asked amount of bytes, quit
+ // should only occur, when the environment has already been disposed
+ OSL_ENSURE( m_pBridgeImpl->m_bDisposed , "urp bridge: inconsistent packet, terminating connection." );
+ return sal_False;
+ }
+ return sal_True;
+}
+
+inline sal_Bool OReaderThread::readFlags( struct MessageFlags *pFlags )
+{
+ sal_uInt8 nBitField;
+ if( ! m_unmarshal.unpackInt8( &nBitField ) )
+ {
+ m_pBridgeImpl->addError( "Unexpected end of message header (1)" );
+ return sal_False;
+ }
+
+ if( HDRFLAG_LONGHEADER & nBitField )
+ {
+ // this is a long header, interpret the byte as bitfield
+ pFlags->bTid = (HDRFLAG_NEWTID & nBitField );
+ pFlags->bRequest = (HDRFLAG_REQUEST & nBitField);
+
+ if( pFlags->bRequest )
+ {
+ // request
+ pFlags->bType = ( HDRFLAG_NEWTYPE & nBitField );
+ pFlags->bOid = ( HDRFLAG_NEWOID & nBitField );
+ pFlags->bIgnoreCache = ( HDRFLAG_IGNORECACHE & nBitField );
+ pFlags->bMoreFlags = ( HDRFLAG_MOREFLAGS & nBitField );
+
+ if( pFlags->bMoreFlags )
+ {
+ // another byte with flags
+ sal_Int8 moreFlags;
+ if( ! m_unmarshal.unpackInt8( &moreFlags ) )
+ {
+ m_pBridgeImpl->addError( "Unexpected end of message header (2)" );
+ return sal_False;
+ }
+ pFlags->bSynchronous = ( HDRFLAG_SYNCHRONOUS & moreFlags );
+ pFlags->bMustReply = ( HDRFLAG_MUSTREPLY & moreFlags );
+ OSL_ENSURE( (pFlags->bSynchronous && pFlags->bMustReply) ||
+ (!pFlags->bSynchronous && !pFlags->bMustReply),
+ "urp-bridge : customized calls currently not supported !");
+ }
+
+ if( HDRFLAG_LONGMETHODID & nBitField )
+ {
+ // methodid as unsigned short
+ if( ! m_unmarshal.unpackInt16( &(pFlags->nMethodId )) )
+ {
+ m_pBridgeImpl->addError( "Unexpected end of message header (3)" );
+ return sal_False;
+ }
+ }
+ else
+ {
+ sal_uInt8 id;
+ if( ! m_unmarshal.unpackInt8( &id ) )
+ {
+ m_pBridgeImpl->addError( "Unexpected end of message header (4)" );
+ return sal_False;
+ }
+ pFlags->nMethodId = (sal_uInt16) id;
+ }
+ }
+ else
+ {
+ // reply
+ pFlags->bRequest = sal_False;
+ pFlags->bException = ( HDRFLAG_EXCEPTION & nBitField );
+ }
+ }
+ else
+ {
+ // short request
+ pFlags->bRequest = sal_True;
+ if( 0x40 & nBitField )
+ {
+ sal_uInt8 lower;
+ if( ! m_unmarshal.unpackInt8( &lower ) )
+ {
+ m_pBridgeImpl->addError( "Unexpected end of message header (5)" );
+ return sal_False;
+ }
+ pFlags->nMethodId = ( nBitField & 0x3f ) << 8 | lower;
+ }
+ else
+ {
+ pFlags->nMethodId = ( nBitField & 0x3f );
+ }
+ }
+ return sal_True;
+}
+
+void OReaderThread::run()
+{
+ // This vars are needed to hold oid,tid and type information, which should not be cached.
+ Type lastTypeNoCache;
+ OUString lastOidNoCache;
+ ByteSequence lastTidNoCache;
+
+ while( m_bContinue )
+ {
+ sal_Int32 nMessageCount;
+ if( ! readBlock( &nMessageCount ) )
+ {
+ disposeEnvironment();
+ break;
+ }
+
+ uno_Environment *pEnvRemote = 0;
+ m_pEnvRemote->harden( &pEnvRemote , m_pEnvRemote );
+ if( !pEnvRemote )
+ {
+ // environment has been disposed already, quit here
+ break;
+ }
+ ServerMultiJob *pMultiJob = 0;
+ remote_Interface *pLastRemoteI = 0;
+ while( ! m_unmarshal.finished() )
+ {
+#ifdef BRIDGES_URP_PROT
+ sal_uInt32 nLogStart = m_unmarshal.getPos();
+ sal_Bool bIsOneWay = sal_False;
+ OUString sMemberName;
+#endif
+ MessageFlags flags;
+
+ if( ! readFlags( &flags ) )
+ {
+ m_pBridgeImpl->addError( "incomplete message, skipping block" );
+ OSL_ENSURE ( 0 , "urp-bridge : incomplete message, skipping block" );
+ break;
+ }
+
+ // use these ** to access the ids fast ( avoid acquire/release calls )
+ sal_Sequence **ppLastTid = flags.bIgnoreCache ?
+ (sal_Sequence **) &lastTidNoCache :
+ (sal_Sequence **) &(m_pBridgeImpl->m_lastInTid);
+ rtl_uString **ppLastOid = flags.bIgnoreCache ?
+ (rtl_uString ** ) &lastOidNoCache :
+ (rtl_uString ** ) &(m_pBridgeImpl->m_lastInOid);
+ typelib_TypeDescriptionReference **ppLastType =
+ flags.bIgnoreCache ?
+ (typelib_TypeDescriptionReference ** ) &lastTypeNoCache :
+ (typelib_TypeDescriptionReference ** ) &(m_pBridgeImpl->m_lastInType);
+
+ // get new type
+ if( flags.bType )
+ {
+ typelib_TypeDescriptionReference *pTypeRef = 0;
+ if( m_unmarshal.unpackType( &pTypeRef ) )
+ {
+ // release the old type
+ typelib_typedescriptionreference_release( *ppLastType );
+ // set the new type
+ *ppLastType = pTypeRef;
+
+ // no release on pTypeRef necessary (will be released by type dtor)
+ }
+ else
+ {
+ typelib_typedescriptionreference_release( pTypeRef );
+ m_pBridgeImpl->addError( "error during unpacking (maybe cached) interface type" );
+ OSL_ENSURE( 0 , "urp-bridge : error during unpacking interface type, terminating connection" );
+ disposeEnvironment();
+ break;
+ }
+ if( m_pBridgeImpl->m_lastInType.getTypeClass() != TypeClass_INTERFACE )
+ {
+ OUStringBuffer sMessage;
+ sMessage.appendAscii( "interface type is not of typeclass interface (" );
+ sMessage.append( (sal_Int32) m_pBridgeImpl->m_lastInType.getTypeClass() );
+ m_pBridgeImpl->addError( sMessage.makeStringAndClear() );
+ OSL_ENSURE( 0 , "urp-bridge : not an interface type" );
+ disposeEnvironment();
+ break;
+ }
+ }
+ if( flags.bOid )
+ {
+ rtl_uString *pOid = 0;
+ if( m_unmarshal.unpackOid( &pOid ) )
+ {
+ rtl_uString_release( *ppLastOid );
+ *ppLastOid = pOid;
+ }
+ else
+ {
+ rtl_uString_release( pOid );
+ m_pBridgeImpl->addError( "error during unpacking (maybe cached) oid" );
+ OSL_ENSURE( 0 , "urp-bridge : error during unpacking cached data, terminating connection" );
+ disposeEnvironment();
+ break;
+ }
+ }
+
+ if( flags.bTid )
+ {
+ sal_Sequence *pSeq = 0;
+ if( m_unmarshal.unpackTid( &pSeq ) )
+ {
+ rtl_byte_sequence_release( *ppLastTid );
+ *ppLastTid = pSeq;
+ }
+ else
+ {
+ rtl_byte_sequence_release( pSeq );
+
+ m_pBridgeImpl->addError( "error during unpacking (maybe cached) tid" );
+ OSL_ENSURE( 0 , "urp-bridge : error during unpacking cached data, terminating connection" );
+ disposeEnvironment();
+ break;
+ }
+ }
+
+ // do the job
+ if( flags.bRequest )
+ {
+ bool bHasCc = m_pBridgeImpl->m_properties.bCurrentContext
+ && flags.nMethodId != REMOTE_RELEASE_METHOD_INDEX
+ && !rtl::OUString( *ppLastOid ).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(
+ g_NameOfUrpProtocolPropertiesObject ) );
+ remote_Interface * pCc = 0;
+ if ( bHasCc )
+ {
+ typelib_TypeDescription * pType = 0;
+ TYPELIB_DANGER_GET(
+ &pType,
+ XCurrentContext::static_type().getTypeLibType() );
+ bool ok = m_unmarshal.unpack( &pCc, pType );
+ TYPELIB_DANGER_RELEASE( pType );
+ if ( !ok )
+ {
+ OSL_ENSURE(
+ false,
+ ("urp_bridge: error while unpacking current"
+ " context") );
+ disposeEnvironment();
+ break;
+ }
+ }
+
+ //--------------------------
+ // handle request
+ //--------------------------
+ // get the membertypedescription
+ typelib_InterfaceMethodTypeDescription *pMethodType = 0;
+ typelib_InterfaceAttributeTypeDescription *pAttributeType = 0;
+ sal_Bool bIsSetter = sal_False;
+
+ if( getMemberTypeDescription(
+ &pAttributeType, &pMethodType, &bIsSetter,
+ flags.nMethodId, *ppLastType ) )
+ {
+ if( ! pLastRemoteI || flags.bOid || flags.bType )
+ {
+ // a new interface must be retrieved
+
+ // retrieve the interface NOW from the environment
+ // (avoid race conditions : oneway followed by release )
+ typelib_InterfaceTypeDescription *pInterfaceType = 0;
+
+ TYPELIB_DANGER_GET(
+ (typelib_TypeDescription ** ) &pInterfaceType ,
+ *ppLastType );
+ if( !pInterfaceType )
+ {
+ OUStringBuffer sMessage;
+ sMessage.appendAscii( "Couldn't retrieve type description for type " );
+ sMessage.append( OUString( (*ppLastType)->pTypeName ) );
+ m_pBridgeImpl->addError( sMessage.makeStringAndClear() );
+ delete pMultiJob;
+ pMultiJob = 0;
+ disposeEnvironment();
+ pLastRemoteI = 0; // stubs are released during dispose eitherway
+ break;
+ }
+ pEnvRemote->pExtEnv->getRegisteredInterface(
+ pEnvRemote->pExtEnv, ( void ** ) &pLastRemoteI,
+ *ppLastOid, pInterfaceType );
+ TYPELIB_DANGER_RELEASE( (typelib_TypeDescription * )pInterfaceType );
+
+ if( !pLastRemoteI &&
+ REMOTE_RELEASE_METHOD_INDEX != flags.nMethodId &&
+ 0 == rtl_ustr_ascii_compare_WithLength(
+ (*ppLastOid)->buffer, (*ppLastOid)->length, g_NameOfUrpProtocolPropertiesObject ) )
+ {
+ // check for bridge internal propertyobject
+ pLastRemoteI = m_pBridgeImpl->m_pPropertyObject;
+ pLastRemoteI->acquire( pLastRemoteI );
+ flags.bBridgePropertyCall = sal_True;
+ }
+
+ // NOTE : Instance provider is called in the executing thread
+ // Otherwise, instance provider may block the bridge
+ }
+
+ sal_Bool bCallIsOneway = sal_False;
+ if( flags.bMoreFlags )
+ {
+ // flags override the default !
+ bCallIsOneway = ! flags.bSynchronous;
+ }
+ else if( pMethodType && pMethodType->bOneWay )
+ {
+ bCallIsOneway = sal_True;
+ }
+
+ if( pMultiJob && ! flags.bTid && bCallIsOneway && ! pMultiJob->isFull())
+ {
+ // add to the existing multijob, nothing to do here
+ }
+ else
+ {
+ // create a new multijob
+ if( pMultiJob )
+ {
+ // there exists an old one, start it first.
+ pMultiJob->initiate();
+ }
+
+ pMultiJob = new ServerMultiJob(
+ pEnvRemote,
+ static_cast< remote_Context * >(
+ pEnvRemote->pContext ),
+ *ppLastTid, m_pBridgeImpl, &m_unmarshal,
+ nMessageCount );
+ }
+
+ pMultiJob->setCurrentContext( bHasCc, pCc );
+ pMultiJob->setIgnoreCache( flags.bIgnoreCache );
+ pMultiJob->setType( *ppLastType );
+ if( pMethodType )
+ {
+ pMultiJob->setMethodType( pMethodType ,
+ REMOTE_RELEASE_METHOD_INDEX == flags.nMethodId,
+ bCallIsOneway );
+ }
+ else if( pAttributeType )
+ {
+ pMultiJob->setAttributeType( pAttributeType, bIsSetter, bCallIsOneway );
+ }
+ else
+ {
+ OSL_ASSERT( 0 );
+ }
+
+ if( pLastRemoteI )
+ pMultiJob->setInterface( pLastRemoteI );
+ else
+ pMultiJob->setOid( *ppLastOid );
+ } /* getMemberTypeDescription */
+ else
+ {
+ delete pMultiJob;
+ pMultiJob = 0;
+ pLastRemoteI = 0; // stubs are released during dispose eitherway
+ disposeEnvironment();
+ break;
+ }
+#ifdef BRIDGES_URP_PROT
+ bIsOneWay = pMethodType && pMethodType->bOneWay;
+ sMemberName = pMethodType ?
+ pMethodType->aBase.pMemberName :
+ pAttributeType->aBase.pMemberName;
+ sal_uInt32 nLogHeader = m_unmarshal.getPos();
+#endif
+ if( ! pMultiJob->extract( ) )
+ {
+ // severe error during extracting, dispose
+ delete pMultiJob;
+ pMultiJob = 0;
+ pLastRemoteI = 0; // stubs are released during dispose eitherway
+ disposeEnvironment();
+ break;
+ }
+
+#ifdef BRIDGES_URP_PROT
+ urp_logServingRequest(
+ m_pBridgeImpl, m_unmarshal.getPos() - nLogStart,
+ m_unmarshal.getPos() - nLogHeader,
+ !bIsOneWay,
+ sMemberName );
+#endif
+ if ( flags.bBridgePropertyCall )
+ {
+ // call to the bridge internal object.
+ // these calls MUST be executed within the dispatcher thread in order
+ // to synchronize properly with protocol changes
+ // NOTE : Threadid is not preserved for this call.
+
+ // lock the marshaling NOW !
+ {
+ MutexGuard guard( m_pBridgeImpl->m_marshalingMutex );
+
+ pMultiJob->execute();
+
+ if( m_pBridgeImpl->m_pPropertyObject->changesHaveBeenCommited() )
+ {
+ Properties props;
+ props = m_pBridgeImpl->m_pPropertyObject->getCommitedChanges();
+
+ // This call modified the protocol, apply the changes NOW !
+ m_pBridgeImpl->applyProtocolChanges( props );
+ }
+ }
+ delete pMultiJob;
+ pMultiJob = 0;
+ }
+ }
+ else
+ {
+ //--------------------------
+ // handle reply
+ //--------------------------
+ if( pMultiJob )
+ {
+ pMultiJob->initiate();
+ pMultiJob = 0;
+ }
+ if( pLastRemoteI )
+ {
+ pLastRemoteI->release( pLastRemoteI );
+ pLastRemoteI = 0;
+ }
+ ClientJob *pClientJob =
+ m_pBridgeImpl->m_clientJobContainer.remove( *( ByteSequence * )ppLastTid );
+
+ // Bridge MUST be already disposed, otherwise we got a wrong threadid
+ // from remote !
+ OSL_ASSERT( pClientJob || m_pBridgeImpl->m_bDisposed );
+ if( ! pClientJob )
+ {
+ OUStringBuffer error( 128 );
+ error.appendAscii( "ThreadID " );
+ OString o = byteSequence2HumanReadableString( *(ByteSequence* )ppLastTid );
+ error.appendAscii( o.getStr(), o.getLength() );
+ error.appendAscii( " unknown, so couldn't unmarshal reply" );
+ m_pBridgeImpl->addError( error.makeStringAndClear() );
+ pLastRemoteI = 0;
+ disposeEnvironment();
+ break;
+ }
+
+ pClientJob->m_bExceptionOccured = flags.bException;
+
+ pClientJob->setUnmarshal( &m_unmarshal );
+#ifdef BRIDGES_URP_PROT
+ sMemberName = pClientJob->m_pMethodType ?
+ pClientJob->m_pMethodType->aBase.pMemberName :
+ pClientJob->m_pAttributeType->aBase.pMemberName;
+ sal_uInt32 nLogHeader = m_unmarshal.getPos();
+#endif
+ if( ! pClientJob->extract( ) )
+ {
+ // severe error during extracting, dispose
+ pLastRemoteI = 0; // stubs are released during dispose eitherway
+ disposeEnvironment();
+ break;
+ }
+#ifdef BRIDGES_URP_PROT
+ urp_logGettingReply(
+ m_pBridgeImpl, m_unmarshal.getPos() - nLogStart,
+ m_unmarshal.getPos() - nLogHeader, sMemberName );
+#endif
+ sal_Bool bBridgePropertyCallAndWaitingForReply =
+ pClientJob->isBridgePropertyCall();
+
+ pClientJob->initiate();
+
+ if( bBridgePropertyCallAndWaitingForReply )
+ {
+ // NOTE : This must be the reply for commit change. The new properties
+ // are now applied by the clientJob thread, but the reader thread
+ // must wait for it, because the next message on the wire already
+ // uses the new protocol settings.
+ // waiting for the commit change reply
+ m_pBridgeImpl->m_pPropertyObject->waitUntilChangesAreCommitted();
+ }
+ }
+ } // end while( !m_unmarshal.finished() )
+
+ if( pLastRemoteI )
+ pLastRemoteI->release( pLastRemoteI );
+
+ if( pMultiJob )
+ pMultiJob->initiate();
+
+ if( pEnvRemote )
+ pEnvRemote->release( pEnvRemote );
+ }
+
+ if( m_pConnection )
+ {
+ m_pConnection->release( m_pConnection );
+ m_pConnection = 0;
+ }
+}
+}