summaryrefslogtreecommitdiff
path: root/bridges/source/remote/urp/urp_propertyobject.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/remote/urp/urp_propertyobject.cxx')
-rw-r--r--bridges/source/remote/urp/urp_propertyobject.cxx796
1 files changed, 796 insertions, 0 deletions
diff --git a/bridges/source/remote/urp/urp_propertyobject.cxx b/bridges/source/remote/urp/urp_propertyobject.cxx
new file mode 100644
index 000000000000..323faee2e929
--- /dev/null
+++ b/bridges/source/remote/urp/urp_propertyobject.cxx
@@ -0,0 +1,796 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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 <stdlib.h>
+#include <osl/diagnose.h>
+
+#include <rtl/random.h>
+
+#include <uno/data.h>
+
+#include "com/sun/star/bridge/InvalidProtocolChangeException.hpp"
+#include <com/sun/star/bridge/XProtocolProperties.hpp>
+
+#include "urp_propertyobject.hxx"
+#include "urp_dispatch.hxx"
+#include "urp_bridgeimpl.hxx"
+#include "urp_job.hxx"
+
+using namespace ::rtl;
+using namespace ::osl;
+using namespace ::com::sun::star::bridge;
+using namespace ::com::sun::star::uno;
+
+using namespace bridges_urp;
+
+extern "C" {
+
+static void SAL_CALL staticAcquire( remote_Interface *pRemoteI )
+{
+ PropertyObject *pProperties = (PropertyObject *) pRemoteI;
+ pProperties->thisAcquire();
+}
+
+static void SAL_CALL staticRelease( remote_Interface *pRemoteI )
+{
+ PropertyObject *pProperties = (PropertyObject *) pRemoteI;
+ pProperties->thisRelease();
+}
+
+static void SAL_CALL staticDispatch(
+ remote_Interface * pRemoteI, typelib_TypeDescription const * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException )
+{
+ PropertyObject *pProperties = (PropertyObject *) pRemoteI;
+ pProperties->thisDispatch( pMemberType, pReturn, pArgs, ppException );
+}
+
+}
+
+namespace bridges_urp
+{
+// some nice constants ....
+static const sal_Int32 METHOD_QUERY_INTERFACE = 0;
+static const sal_Int32 METHOD_GET_PROPERTIES = 3;
+static const sal_Int32 METHOD_REQUEST_CHANGE = 4;
+static const sal_Int32 METHOD_COMMIT_CHANGE = 5;
+
+static const sal_Int32 PROPERTY_BRIDGEID = 0;
+static const sal_Int32 PROPERTY_TYPECACHESIZE = 1;
+static const sal_Int32 PROPERTY_OIDCACHESIZE = 2;
+static const sal_Int32 PROPERTY_TIDCACHESIZE = 3;
+static const sal_Int32 PROPERTY_SUPPORTEDVERSIONS = 4;
+static const sal_Int32 PROPERTY_VERSION =5;
+static const sal_Int32 PROPERTY_FLUSHBLOCKSIZE = 6;
+static const sal_Int32 PROPERTY_ONEWAYTIMEOUT_MUSEC = 7;
+static const sal_Int32 PROPERTY_SUPPORTSMUSTREPLY = 8;
+static const sal_Int32 PROPERTY_SUPPERTSSYNCHRONOUS = 9;
+static const sal_Int32 PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS = 10;
+static const sal_Int32 PROPERTY_CLEARCACHE = 11;
+static const sal_Int32 PROPERTY_NEGOTIATE = 12;
+static const sal_Int32 PROPERTY_FORCESYNCHRONOUS = 13;
+static const sal_Int32 PROPERTY_CURRENTCONTEXT = 14;
+
+static const sal_Int32 MAX_PROPERTIES = PROPERTY_CURRENTCONTEXT +1;
+
+const sal_Char *g_aPropertyName[] =
+{
+ "BridgeId",
+ "TypeCacheSize",
+ "OidCacheSize",
+ "TidCacheSize",
+ "SupportedVersion",
+ "Version",
+ "FlushBlockSize",
+ "OnewayTimeoutMUSEC",
+ "SupportsMustReply",
+ "SupportsSynchronous",
+ "SupportsMultipleSynchronous",
+ "ClearCache",
+ "Negotiate",
+ "ForceSynchronous",
+ "CurrentContext"
+};
+
+// nice little helper functions for conversion
+template< class t >
+void assignToIdl( ProtocolProperty *pIdl, sal_Int32 nIndex, const t &value )
+{
+ pIdl->Name = OUString::createFromAscii( g_aPropertyName[nIndex] );
+ ( *(::com::sun::star::uno::Any *)&(pIdl->Value) ) <<= value;
+}
+
+template< class t >
+void assignFromIdl( t * p, const ProtocolProperty & property )
+{
+ property.Value >>=*p;
+}
+
+static sal_Int32 getIndexFromIdl( const ProtocolProperty & property )
+{
+ sal_Int32 nResult = -1;
+ for( sal_Int32 i = 0 ; i < MAX_PROPERTIES ; i ++ )
+ {
+ if( 0 == property.Name.compareToAscii( g_aPropertyName[i] ) )
+ {
+ nResult = i;
+ break;
+ }
+ }
+ return nResult;
+}
+
+static sal_Int32 getIndexFromString( const OUString & property )
+{
+ sal_Int32 nResult = -1;
+ for( sal_Int32 i = 0 ; i < MAX_PROPERTIES ; i ++ )
+ {
+ if( 0 == property.compareToAscii( g_aPropertyName[i] ) )
+ {
+ nResult = i;
+ break;
+ }
+ }
+ return nResult;
+}
+
+static sal_Bool assignFromIdlToStruct( Properties *pProps, const ProtocolProperty &idl )
+{
+ sal_Bool bReturn = sal_True;
+
+ sal_Int32 nIndex = getIndexFromIdl( idl );
+ if( nIndex >= 0 )
+ {
+ switch( nIndex )
+ {
+ case PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS:
+ assignFromIdl( &(pProps->bSupportsMultipleSynchronous) , idl );
+ break;
+ case PROPERTY_SUPPERTSSYNCHRONOUS:
+ assignFromIdl( &(pProps->bSupportsMustReply) , idl );
+ break;
+ case PROPERTY_SUPPORTSMUSTREPLY:
+ assignFromIdl( &(pProps->bSupportsSynchronous) , idl );
+ break;
+ case PROPERTY_ONEWAYTIMEOUT_MUSEC:
+ assignFromIdl( &(pProps->nOnewayTimeoutMUSEC) , idl );
+ break;
+ case PROPERTY_BRIDGEID:
+ assignFromIdl( (Sequence< sal_Int8 > * )&(pProps->seqBridgeID), idl );
+ break;
+ case PROPERTY_TYPECACHESIZE:
+ assignFromIdl( &(pProps->nTypeCacheSize) , idl );
+ break;
+ case PROPERTY_OIDCACHESIZE:
+ assignFromIdl( &(pProps->nOidCacheSize) , idl );
+ break;
+ case PROPERTY_TIDCACHESIZE:
+ assignFromIdl( &(pProps->nTidCacheSize), idl );
+ break;
+ case PROPERTY_SUPPORTEDVERSIONS:
+ assignFromIdl( &(pProps->sSupportedVersions) , idl );
+ break;
+ case PROPERTY_VERSION:
+ assignFromIdl( &(pProps->sVersion) , idl );
+ break;
+ case PROPERTY_FLUSHBLOCKSIZE:
+ assignFromIdl( &(pProps->nFlushBlockSize) ,idl );
+ break;
+ case PROPERTY_CLEARCACHE:
+ assignFromIdl( &(pProps->bClearCache) ,idl );
+ break;
+ case PROPERTY_NEGOTIATE:
+ assignFromIdl( &(pProps->bNegotiate) ,idl );
+ break;
+ case PROPERTY_FORCESYNCHRONOUS:
+ assignFromIdl( &(pProps->bForceSynchronous) ,idl );
+ break;
+ case PROPERTY_CURRENTCONTEXT:
+ pProps->bCurrentContext = true;
+ break;
+ default:
+ bReturn = sal_False;
+ }
+ }
+ else
+ {
+ bReturn = sal_False;
+ }
+ return bReturn;
+}
+
+static void extractTokens(
+ const ::rtl::OUString &sProps , ::std::list< OUString > &lst )
+{
+ sal_Int32 nNext = 0;
+ while ( sal_True )
+ {
+ sal_Int32 nStart = nNext;
+ nNext = sProps.indexOf( ',' , nNext );
+ if( -1 == nNext )
+ {
+ lst.push_back( sProps.copy( nStart, sProps.getLength() - nStart ) );
+ break;
+ }
+ lst.push_back( sProps.copy( nStart , nNext - nStart ) );
+ nNext ++;
+ }
+}
+
+
+static void assignFromStringToPropSeq( const OUString &sProps, uno_Sequence **ppPropertySeq)
+{
+ ::std::list< OUString > lst;
+ extractTokens( sProps , lst );
+
+ typelib_TypeDescription *pSequenceType = 0;
+ getCppuType( (Sequence< ProtocolProperty > *)0).getDescription( &pSequenceType );
+ uno_Sequence *pSeq = 0;
+ uno_sequence_construct( &pSeq , pSequenceType , 0, lst.size() , 0 );
+ ProtocolProperty *pElements = (ProtocolProperty * ) pSeq->elements;
+
+ sal_Int32 i = 0;
+ for( ::std::list< OUString >::iterator ii = lst.begin() ; ii != lst.end() ; ++ ii, i++ )
+ {
+ sal_Int32 nAssign = (*ii).indexOf( '=' );
+ if( -1 == nAssign )
+ {
+ OString o = OUStringToOString( *ii, RTL_TEXTENCODING_ASCII_US );
+ OSL_ENSURE( !"wrong protocol propertyt format, ignored", o.getStr() );
+ }
+ OUString sPropName = (*ii).copy( 0, nAssign );
+ OUString sValue = (*ii).copy( nAssign +1, (*ii).getLength() - nAssign -1 );
+
+ sal_Int32 nIndex = getIndexFromString( sPropName );
+ if( -1 == nIndex )
+ {
+ OString o = OUStringToOString( sPropName , RTL_TEXTENCODING_ASCII_US);
+ OSL_ENSURE( !"unknown protocol property, ignored", o.getStr() );
+ }
+ switch( nIndex )
+ {
+ // voids
+ case PROPERTY_CURRENTCONTEXT:
+ pElements[i].Name = OUString::createFromAscii(
+ g_aPropertyName[nIndex] );
+ break;
+ // bools
+ case PROPERTY_CLEARCACHE:
+ case PROPERTY_NEGOTIATE:
+ case PROPERTY_FORCESYNCHRONOUS:
+ {
+ sal_Bool bClearCache = (sal_Bool ) sValue.toInt32();
+ assignToIdl( &(pElements[i]) , nIndex , bClearCache );
+ break;
+ }
+ // ints
+ case PROPERTY_TYPECACHESIZE:
+ case PROPERTY_OIDCACHESIZE:
+ case PROPERTY_TIDCACHESIZE:
+ case PROPERTY_FLUSHBLOCKSIZE:
+ case PROPERTY_ONEWAYTIMEOUT_MUSEC:
+ {
+ sal_Int32 nValue = sValue.toInt32();
+ assignToIdl( &(pElements[i]) , nIndex , nValue );
+ break;
+ }
+
+ // strings
+ case PROPERTY_VERSION:
+ assignToIdl( &(pElements[i]) , nIndex , sValue );
+ break;
+ default:
+ OString o = OUStringToOString( sPropName, RTL_TEXTENCODING_ASCII_US );
+ OSL_ENSURE( !"readonly protocol property, ignored" , o.getStr() );
+ }
+ }
+ *ppPropertySeq = pSeq;
+ typelib_typedescription_release( pSequenceType );
+}
+
+static void assignFromPropSeqToStruct( uno_Sequence *pSeq , struct Properties *pProps )
+{
+ sal_Int32 i;
+ ProtocolProperty *pElements = (ProtocolProperty *)pSeq->elements;
+ for( i = 0 ; i < pSeq->nElements ; i ++ )
+ {
+ assignFromIdlToStruct( pProps , pElements[i] );
+ }
+}
+
+void assignFromStringToStruct( const OUString & sProps , struct Properties *pProps )
+{
+ uno_Sequence *pSeq = 0;
+ assignFromStringToPropSeq( sProps , &pSeq );
+ assignFromPropSeqToStruct( pSeq , pProps );
+ uno_type_destructData( &pSeq, getCppuType( (Sequence< ProtocolProperty > *)0).getTypeLibType(),0);
+}
+
+
+//----------------------------------------------------------------------------------------------
+// PropertyObject implementation
+PropertyObject::PropertyObject(
+ struct Properties *pLocalSetting , uno_Environment *pEnvRemote, urp_BridgeImpl *pImpl )
+ : m_commitChangeCondition( osl_createCondition() )
+ , m_nRefCount( 0 )
+ , m_pBridgeImpl( pImpl )
+ , m_pLocalSetting( pLocalSetting )
+ , m_pEnvRemote( pEnvRemote )
+ , m_bRequestChangeHasBeenCalled( sal_False )
+ , m_bServerWaitingForCommit( sal_False )
+ , m_bApplyProperties( sal_False )
+{
+ acquire = staticAcquire;
+ release = staticRelease;
+ pDispatcher = staticDispatch;
+}
+
+PropertyObject::~PropertyObject()
+{
+ osl_destroyCondition( m_commitChangeCondition );
+}
+
+void SAL_CALL PropertyObject::thisDispatch(
+ typelib_TypeDescription const * pMemberType, void * pReturn, void * ppArgs[],
+ uno_Any ** ppException )
+{
+ OSL_ASSERT( pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD );
+
+ typelib_InterfaceMethodTypeDescription *pMethodType =
+ ( typelib_InterfaceMethodTypeDescription * ) pMemberType;
+
+ switch( pMethodType->aBase.nPosition )
+ {
+ case METHOD_QUERY_INTERFACE:
+ OSL_ENSURE( 0 , "not implemented yet !" );
+ break;
+ case METHOD_GET_PROPERTIES:
+ {
+ implGetProperties( (uno_Sequence **) pReturn );
+ *ppException = 0;
+ break;
+ }
+ case METHOD_COMMIT_CHANGE:
+ {
+ implCommitChange( *(uno_Sequence ** ) ppArgs[0] , ppException );
+ break;
+ }
+ case METHOD_REQUEST_CHANGE:
+ {
+ *(sal_Int32 *) pReturn = implRequestChange( *(sal_Int32 *)ppArgs[0], ppException );
+ break;
+ }
+ default:
+ OSL_ENSURE( 0 , "unkown method !" );
+ }
+}
+
+void SAL_CALL PropertyObject::localGetPropertiesFromRemote( struct Properties *pR )
+{
+ OUString oid = OUString::createFromAscii( g_NameOfUrpProtocolPropertiesObject );
+
+ typelib_TypeDescription *pInterfaceType = 0;
+ getCppuType( (Reference< XProtocolProperties > *) 0 ).getDescription( &pInterfaceType );
+
+ if( !pInterfaceType->bComplete )
+ {
+ typelib_typedescription_complete( &pInterfaceType );
+ }
+
+ typelib_TypeDescription *pMethodType = 0;
+ typelib_typedescriptionreference_getDescription(
+ &pMethodType,
+ ((typelib_InterfaceTypeDescription*) pInterfaceType)->ppAllMembers[METHOD_GET_PROPERTIES] );
+
+
+ uno_Sequence *pResult = 0;
+ uno_Any exception;
+ uno_Any *pException = &exception;
+ urp_sendRequest( m_pEnvRemote,
+ pMethodType,
+ oid.pData,
+ (typelib_InterfaceTypeDescription*) pInterfaceType,
+ &pResult,
+ 0,
+ &pException );
+
+ if( pException )
+ {
+ OSL_ENSURE( 0 , "remote urp-bridge doesn't support property-object" );
+ uno_any_destruct( pException , 0 );
+ return;
+ }
+
+ ProtocolProperty *pP = (ProtocolProperty * ) pResult->elements;
+ for( sal_Int32 i = 0; i < pResult->nElements ; i ++ )
+ {
+ if( ! assignFromIdlToStruct( pR , pP[i] ) )
+ {
+ OSL_ENSURE( 0 , "unknown property !!!!" );
+ }
+ }
+
+ typelib_typedescription_release( pInterfaceType );
+ typelib_typedescription_release( pMethodType );
+}
+
+
+// implementation for call from remote
+void SAL_CALL PropertyObject::implGetProperties( uno_Sequence **ppReturnValue )
+{
+ typelib_TypeDescription *pElementType= 0;
+ getCppuType( (Sequence< ProtocolProperty > *)0).getDescription( &pElementType );
+
+ OSL_ENSURE( pElementType , "Couldn't get property type" );
+
+ *ppReturnValue = 0;
+ uno_sequence_construct( ppReturnValue , pElementType , 0, MAX_PROPERTIES , 0 );
+ ProtocolProperty *pElements = (ProtocolProperty * ) ( *ppReturnValue )->elements;
+ Properties *pP = m_pLocalSetting;
+
+ assignToIdl( &(pElements[PROPERTY_BRIDGEID]),PROPERTY_BRIDGEID, toUnoSequence(pP->seqBridgeID) );
+ assignToIdl( &(pElements[PROPERTY_TYPECACHESIZE]),PROPERTY_TYPECACHESIZE,pP->nTypeCacheSize );
+ assignToIdl( &(pElements[PROPERTY_OIDCACHESIZE]),PROPERTY_OIDCACHESIZE, pP->nOidCacheSize );
+ assignToIdl( &(pElements[PROPERTY_TIDCACHESIZE]),PROPERTY_TIDCACHESIZE, pP->nTidCacheSize );
+ assignToIdl( &(pElements[PROPERTY_SUPPORTEDVERSIONS]),PROPERTY_SUPPORTEDVERSIONS, pP->sSupportedVersions );
+ assignToIdl( &(pElements[PROPERTY_VERSION]),PROPERTY_VERSION, pP->sVersion );
+ assignToIdl( &(pElements[PROPERTY_FLUSHBLOCKSIZE]), PROPERTY_FLUSHBLOCKSIZE,pP->nFlushBlockSize );
+ assignToIdl( &(pElements[PROPERTY_ONEWAYTIMEOUT_MUSEC]), PROPERTY_ONEWAYTIMEOUT_MUSEC, pP->nOnewayTimeoutMUSEC );
+ assignToIdl( &(pElements[PROPERTY_SUPPORTSMUSTREPLY]), PROPERTY_SUPPORTSMUSTREPLY, pP->bSupportsMustReply );
+ assignToIdl( &(pElements[PROPERTY_SUPPERTSSYNCHRONOUS]), PROPERTY_SUPPERTSSYNCHRONOUS, pP->bSupportsSynchronous );
+ assignToIdl( &(pElements[PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS]), PROPERTY_SUPPORTSMULTIPLESYNCHRONOUS, pP->bSupportsMultipleSynchronous );
+ assignToIdl( &(pElements[PROPERTY_CLEARCACHE]), PROPERTY_CLEARCACHE, pP->bClearCache );
+
+ typelib_typedescription_release( pElementType );
+}
+
+//----------------------------------------------------------------------------------------------
+sal_Int32 SAL_CALL PropertyObject::localRequestChange( )
+{
+ sal_Int32 nResult = 0;
+ sal_Bool bCall = sal_True;
+
+ // disallow marshaling NOW !
+ ClearableMutexGuard marshalingGuard( m_pBridgeImpl->m_marshalingMutex );
+ {
+ MutexGuard guard( m_mutex );
+ if( m_bRequestChangeHasBeenCalled || m_bServerWaitingForCommit )
+ {
+ // another transaction is already underway
+ // try again later !
+ bCall = sal_False;
+ }
+ m_bRequestChangeHasBeenCalled = sal_True;
+
+ if( bCall )
+ {
+ // calulate random number
+ rtlRandomPool pool = rtl_random_createPool ();
+ rtl_random_getBytes( pool , &m_nRandomNumberOfRequest, sizeof( m_nRandomNumberOfRequest ) );
+ rtl_random_destroyPool( pool );
+ }
+ }
+
+ if( bCall )
+ {
+ OUString oid = OUString::createFromAscii( g_NameOfUrpProtocolPropertiesObject );
+
+ // gather types for calling
+ typelib_TypeDescription *pInterfaceType = 0;
+ getCppuType( (Reference< XProtocolProperties > *) 0 ).getDescription( &pInterfaceType );
+
+ if( !pInterfaceType->bComplete )
+ {
+ typelib_typedescription_complete( &pInterfaceType );
+ }
+
+ typelib_TypeDescription *pMethodType = 0;
+ typelib_typedescriptionreference_getDescription(
+ &pMethodType,
+ ((typelib_InterfaceTypeDescription*) pInterfaceType)->ppAllMembers[METHOD_REQUEST_CHANGE] );
+
+ void *pArg1 = &m_nRandomNumberOfRequest;
+ void **ppArgs = &pArg1;
+
+ uno_Any exception;
+ uno_Any *pException = &exception;
+
+ ClientJob job( m_pEnvRemote,
+ 0,
+ m_pBridgeImpl,
+ oid.pData,
+ pMethodType,
+ (typelib_InterfaceTypeDescription*) pInterfaceType,
+ &nResult,
+ ppArgs,
+ &pException );
+
+ // put the call on the line !
+ sal_Bool bSuccess = job.pack();
+
+ // now allow writing on wire again.
+ // NOTE : this has been locked, because it is inevitable to set m_bRequestChangeHasBeenCalled
+ // and call requestChange in an atomar operation. Otherwise, implRequestChange may be called
+ // inbetween and reply, before the request is put on the wire. This certainly would
+ // be confusing for the remote counterpart !
+ marshalingGuard.clear();
+
+ // wait for the reply ...
+ if( bSuccess )
+ {
+ job.wait();
+
+ if( pException )
+ {
+ // the object is unknown on the other side.
+ uno_any_destruct( pException , 0 );
+ nResult = 0;
+ }
+ }
+ else
+ {
+ nResult = 0;
+ }
+ typelib_typedescription_release( pInterfaceType );
+ typelib_typedescription_release( pMethodType );
+ }
+
+ {
+ MutexGuard guard( m_mutex );
+ m_bRequestChangeHasBeenCalled = sal_False;
+ m_bServerWaitingForCommit = ( 0 == nResult );
+ }
+ return nResult;
+}
+
+// implementation for call from remote
+sal_Int32 SAL_CALL PropertyObject::implRequestChange( sal_Int32 nRandomNumber, uno_Any **ppException )
+{
+ sal_Int32 nResult = 0;
+ MutexGuard guard( m_mutex );
+ if( m_bRequestChangeHasBeenCalled )
+ {
+ // this side has also called requestChange, now negotiate, which side is allowed
+ // to commit the change !
+ if( m_nRandomNumberOfRequest > nRandomNumber )
+ {
+ // this side may commit !!!!
+ nResult = 0;
+ }
+ else if( m_nRandomNumberOfRequest == nRandomNumber )
+ {
+ // sorry, try again !
+ nResult = -1;
+ }
+ else if( m_nRandomNumberOfRequest < nRandomNumber )
+ {
+ // the other side may commit !
+ nResult = 1;
+ // m_bServerWaitingForCommit will be set by localRequestChange
+ }
+ }
+ else
+ {
+ // This side has NOT called requestChange, so the other side may commit
+ nResult = 1;
+ m_bServerWaitingForCommit = sal_True;
+ }
+
+ *ppException = 0;
+ return nResult;
+}
+
+
+
+void SAL_CALL PropertyObject::localCommitChange( const ::rtl::OUString &sProps , sal_Bool *pbExceptionThrown )
+{
+ // lock the bridge NOW !
+ // NOTE: it is not allowed for other threads to call, when a commit change is underway.
+ // The remote counterpart cannot if the call following the commit already uses
+ // the new properties or not.
+ MutexGuard guard( m_pBridgeImpl->m_marshalingMutex );
+
+ OUString oid = OUString::createFromAscii( g_NameOfUrpProtocolPropertiesObject );
+
+ osl_resetCondition( m_commitChangeCondition );
+
+ Properties props = *m_pLocalSetting;
+
+ typelib_TypeDescription *pInterfaceType = 0;
+ getCppuType( (Reference< XProtocolProperties > *) 0 ).getDescription( &pInterfaceType );
+
+ if( !pInterfaceType->bComplete )
+ {
+ typelib_typedescription_complete( &pInterfaceType );
+ }
+
+ typelib_TypeDescription *pMethodType = 0;
+ typelib_typedescriptionreference_getDescription(
+ &pMethodType,
+ ((typelib_InterfaceTypeDescription*) pInterfaceType)->ppAllMembers[METHOD_COMMIT_CHANGE] );
+
+// typelib_TypeDescription *pSequenceType= 0;
+
+
+ // extract name/value pairs
+ uno_Sequence *pSeq = 0;
+ assignFromStringToPropSeq( sProps, &pSeq );
+ assignFromPropSeqToStruct( pSeq , &props );
+// ::std::list< OUString > lst;
+// extractTokens( sProps , lst );
+
+// getCppuType( (Sequence< ProtocolProperty > *)0).getDescription( &pSequenceType );
+// uno_sequence_construct( &pSeq , pSequenceType , 0, lst.size() , 0 );
+// ProtocolProperty *pElements = (ProtocolProperty * ) pSeq->elements;
+
+// sal_Int32 i = 0;
+// for( ::std::list< OUString >::iterator ii = lst.begin() ; ii != lst.end() ; ++ ii, i++ )
+// {
+// sal_Int32 nAssign = (*ii).indexOf( '=' );
+// if( -1 == nAssign )
+// {
+// OString o = OUStringToOString( *ii, RTL_TEXTENCODING_ASCII_US );
+// OSL_ENSURE( !"wrong protocol propertyt format, ignored", o.getStr() );
+// }
+// OUString sPropName = (*ii).copy( 0, nAssign );
+// OUString sValue = (*ii).copy( nAssign +1, (*ii).getLength() - nAssign -1 );
+
+// sal_Int32 nIndex = getIndexFromString( sPropName );
+// if( -1 == nIndex )
+// {
+// OString o = OUStringToOString( sPropName , RTL_TEXTENCODING_ASCII_US);
+// OSL_ENSURE( !"unknown protocol property, ignored", o.getStr() );
+// }
+// switch( nIndex )
+// {
+// // bools
+// case PROPERTY_CLEARCACHE:
+// {
+// sal_Bool bClearCache = (sal_Bool ) sValue.toInt32();
+// assignToIdl( &(pElements[i]) , nIndex , bClearCache );
+// break;
+// }
+// // ints
+// case PROPERTY_TYPECACHESIZE:
+// case PROPERTY_OIDCACHESIZE:
+// case PROPERTY_TIDCACHESIZE:
+// case PROPERTY_FLUSHBLOCKSIZE:
+// case PROPERTY_ONEWAYTIMEOUT_MUSEC:
+// {
+// sal_Int32 nValue = sValue.toInt32();
+// assignToIdl( &(pElements[i]) , nIndex , nValue );
+// break;
+// }
+
+// // strings
+// case PROPERTY_VERSION:
+// assignToIdl( &(pElements[i]) , nIndex , sValue );
+// break;
+// default:
+// OString o = OUStringToOString( sPropName, RTL_TEXTENCODING_ASCII_US );
+// OSL_ENSURE( !"readonly protocol property, ignored" , o.getStr() );
+// }
+// assignFromIdlToStruct( &props, pElements[i] );
+// }
+
+ void *pArg1 = &pSeq;
+ uno_Any exception;
+ uno_Any *pException = &exception;
+
+ ClientJob job( m_pEnvRemote,
+ 0,
+ m_pBridgeImpl,
+ oid.pData,
+ pMethodType,
+ (typelib_InterfaceTypeDescription*) pInterfaceType,
+ 0,
+ &pArg1,
+ &pException );
+ job.setBridgePropertyCall();
+ if( job.pack() )
+ {
+ job.wait();
+ }
+ else
+ {
+ OSL_ASSERT( pException != NULL );
+ }
+
+ ::uno_type_destructData(
+ &pSeq, getCppuType( (Sequence< ProtocolProperty > *)0).getTypeLibType(), 0 );
+
+ *pbExceptionThrown = pException ? sal_True : sal_False;
+
+ if( pException )
+ {
+ OString o = OUStringToOString( ((com::sun::star::uno::Exception*)pException->pData)->Message,
+ RTL_TEXTENCODING_ASCII_US);
+ OSL_ENSURE( !"exception thrown during calling on PropertyObject",o.getStr() );
+ uno_any_destruct( pException , 0 );
+ }
+ else
+ {
+ m_pBridgeImpl->applyProtocolChanges( props );
+ m_bServerWaitingForCommit = sal_False;
+ m_bApplyProperties = sal_False;
+ }
+
+ // let the reader thread go ...
+ osl_setCondition( m_commitChangeCondition );
+
+ typelib_typedescription_release( pMethodType );
+ typelib_typedescription_release( pInterfaceType );
+}
+
+void SAL_CALL PropertyObject::implCommitChange( uno_Sequence *pSequence, uno_Any **ppException )
+{
+ MutexGuard guard( m_mutex );
+ m_propsToBeApplied = *m_pLocalSetting;
+
+ ProtocolProperty *pP = (ProtocolProperty * ) pSequence->elements;
+ for( sal_Int32 i = 0; i < pSequence->nElements ; i ++ )
+ {
+ if( ! assignFromIdlToStruct( &m_propsToBeApplied , pP[i] ) )
+ {
+ InvalidProtocolChangeException exception;
+ Type type = getCppuType( &exception );
+ exception.Message = OUString(RTL_CONSTASCII_USTRINGPARAM("urp: unknown Property "));
+ exception.Message += pP[i].Name;
+ exception.invalidProperty = pP[i];
+ exception.reason = 1;
+
+ uno_type_any_construct( *ppException, &exception, type.getTypeLibType() , 0 );
+
+ m_bApplyProperties = sal_False;
+ m_bServerWaitingForCommit = sal_False;
+ return;
+ }
+ }
+
+ m_bApplyProperties = sal_True;
+ *ppException = 0;
+}
+
+Properties SAL_CALL PropertyObject::getCommitedChanges()
+{
+ MutexGuard guard( m_mutex );
+ OSL_ASSERT( m_bApplyProperties );
+ m_bApplyProperties = sal_False;
+ m_bServerWaitingForCommit = sal_False;
+ return m_propsToBeApplied;
+}
+
+void SAL_CALL PropertyObject::waitUntilChangesAreCommitted()
+{
+ osl_waitCondition( m_commitChangeCondition , 0 );
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */