update dev300-m58
[ooovba.git] / automation / source / testtool / comm_bas.cxx
blobf5073c7c7e58f4d9dffe51e0d43533f3e0b9de16
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: comm_bas.cxx,v $
10 * $Revision: 1.9 $
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_automation.hxx"
34 #include "comm_bas.hxx"
35 #include <tools/errcode.hxx>
36 #include <basic/sbxobj.hxx>
37 #include <basic/sbx.hxx>
38 #ifndef __SBX_SBXVARIABLE_HXX //autogen
39 #include <basic/sbxvar.hxx>
40 #endif
41 #include <vcl/svapp.hxx>
42 #include <automation/communi.hxx>
43 #ifndef _BASIC_TTRESHLP_HXX
44 #include <basic/ttstrhlp.hxx>
45 #endif
47 // Der CommunicationManager hat folgende Elemente:
48 // 1) Properties:
49 // Keine
50 // 2) Methoden:
51 // CommunicationLink StartCommunication( Host, Port )
52 // StopAllCommunication // Alle Kommunikation wird abgebrochen
53 // BOOL IsCommunicationRunning // Läuft noch irgendwas
54 // String GetMyName Der eigene Name
55 // BOOL IsLinkValid( CommunicationLink ) // Ist dieser Link noch gültig
56 // SetCommunicationEventHandler( String ) // Diese Funktion wird aufgerufen bei jedem Event
58 // Der CommunicationLink hat folgende Elemente:
59 // 1) Properties:
60 // Keine
61 // 2) Methoden:
62 // StopCommunication Die Kommunikation wird abgebrochen
63 // String GetMyName Der eigene Name
64 // String GetHostName Der Name des Anderen
65 // Send(String ) String an den Partner schicken
66 // String GetString Ergebnis des letzten Empfangs
69 // Diese Implementation ist ein Beispiel fuer eine tabellengesteuerte
70 // Version, die sehr viele Elemente enthalten kann. Die Elemente werden
71 // je nach Bedarf aus der Tabelle in das Objekt uebernommen.
73 // Das nArgs-Feld eines Tabelleneintrags ist wie folgt verschluesselt:
75 #define _ARGSMASK 0x00FF // Bis zu 255 Argumente
76 #define _RWMASK 0x0F00 // Maske fuer R/W-Bits
77 #define _TYPEMASK 0xF000 // Maske fuer den Typ des Eintrags
79 #define _READ 0x0100 // kann gelesen werden
80 #define _BWRITE 0x0200 // kann as Lvalue verwendet werden
81 #define _LVALUE _BWRITE // kann as Lvalue verwendet werden
82 #define _READWRITE 0x0300 // beides
83 #define _OPT 0x0400 // TRUE: optionaler Parameter
84 #define _METHOD 0x1000 // Masken-Bit fuer eine Methode
85 #define _PROPERTY 0x2000 // Masken-Bit fuer eine Property
86 #define _COLL 0x4000 // Masken-Bit fuer eine Collection
87 // Kombination von oberen Bits:
88 #define _FUNCTION 0x1100 // Maske fuer Function
89 #define _LFUNCTION 0x1300 // Maske fuer Function, die auch als Lvalue geht
90 #define _ROPROP 0x2100 // Maske Read Only-Property
91 #define _WOPROP 0x2200 // Maske Write Only-Property
92 #define _RWPROP 0x2300 // Maske Read/Write-Property
93 #define _COLLPROP 0x4100 // Maske Read-Collection-Element
95 #define COLLNAME "Elements" // Name der Collection, hier mal hart verdrahtet
99 CommunicationWrapper::Methods CommunicationWrapper::aManagerMethods[] = {
100 // Neue Kommunikation aufbauen
101 { "StartCommunication", SbxEMPTY, &CommunicationWrapper::MStartCommunication, 2 | _FUNCTION },
102 // Zwei Named Parameter
103 { "Host", SbxSTRING, NULL, 0 },
104 { "Port", SbxLONG, NULL, 0 },
105 // Alle Kommunikation wird abgebrochen
106 { "StopAllCommunication", SbxEMPTY, &CommunicationWrapper::MStopAllCommunication, 0 | _FUNCTION },
107 // Läuft noch irgendwas
108 { "IsCommunicationRunning", SbxBOOL, &CommunicationWrapper::MIsCommunicationRunning, 0 | _FUNCTION },
109 // Hostname als FQDN erfragen
110 { "GetMyName", SbxSTRING, &CommunicationWrapper::MGetMyName, 0 | _FUNCTION },
111 // Abfragen ob der Link überhaupt noch gültig ist
112 { "IsLinkValid", SbxBOOL, &CommunicationWrapper::MIsLinkValid, 1 | _FUNCTION },
113 // Ein Named Parameter
114 { "Link", SbxOBJECT, NULL, 0 },
115 // Dieser Handler wird dauernd gerufen
116 { "SetCommunicationEventHandler", SbxEMPTY, &CommunicationWrapper::MSetCommunicationEventHandler, 1 | _FUNCTION },
117 // Ein Named Parameter
118 { "FuncName", SbxSTRING, NULL, 0 },
120 { NULL, SbxNULL, NULL, -1 }}; // Tabellenende
127 CommunicationWrapper::Methods CommunicationWrapper::aLinkMethods[] = {
128 // Die Kommunikation wird abgebrochen
129 { "StopCommunication", SbxEMPTY, &CommunicationWrapper::LStopCommunication, 0 | _FUNCTION },
130 // Der eigene Name
131 { "GetMyName", SbxSTRING, &CommunicationWrapper::LGetMyName, 0 | _FUNCTION },
132 // Der Name des Anderen
133 { "GetHostName", SbxSTRING, &CommunicationWrapper::LGetHostName, 0 | _FUNCTION },
134 // String an den Partner schicken
135 { "Send", SbxEMPTY, &CommunicationWrapper::LSend, 1 | _FUNCTION },
136 // Ein Named Parameter
137 { "SendString", SbxSTRING, NULL, 0 },
138 // Ergebnis des letzten Empfangs
139 { "GetString", SbxSTRING, &CommunicationWrapper::LGetString, 0 | _FUNCTION },
141 { NULL, SbxNULL, NULL, -1 }}; // Tabellenende
147 // Konstruktor für den Manager
148 CommunicationWrapper::CommunicationWrapper( const String& rClass ) : SbxObject( rClass )
149 , m_pLink( NULL )
150 , m_bIsManager( TRUE )
151 , m_bCatchOpen( FALSE )
152 , m_pNewLink( NULL )
154 // SetName( CUniString("Manager") );
155 m_pMethods = &aManagerMethods[0];
156 m_pManager = new CommunicationManagerClientViaSocket;
157 m_pManager->SetConnectionOpenedHdl( LINK( this, CommunicationWrapper, Open ) );
158 m_pManager->SetConnectionClosedHdl( LINK( this, CommunicationWrapper, Close ) );
159 m_pManager->SetDataReceivedHdl( LINK( this, CommunicationWrapper, Data ) );
162 // Konstruktor für den Link
163 CommunicationWrapper::CommunicationWrapper( CommunicationLink *pThisLink ) : SbxObject( CUniString("Link") )
164 , m_pLink( pThisLink )
165 , m_bIsManager( FALSE )
166 , m_bCatchOpen( FALSE )
167 , m_pNewLink( NULL )
169 m_pMethods = &aLinkMethods[0];
170 m_pManager = (CommunicationManagerClientViaSocket*)pThisLink->GetCommunicationManager();
173 // Destruktor
174 CommunicationWrapper::~CommunicationWrapper()
176 if ( m_bIsManager )
177 delete m_pManager;
181 // Suche nach einem Element:
182 // Hier wird linear durch die Methodentabelle gegangen, bis eine
183 // passende Methode gefunden wurde.
184 // Wenn die Methode/Property nicht gefunden wurde, nur NULL ohne
185 // Fehlercode zurueckliefern, da so auch eine ganze Chain von
186 // Objekten nach der Methode/Property befragt werden kann.
188 SbxVariable* CommunicationWrapper::Find( const String& rName, SbxClassType t )
190 // Ist das Element bereits vorhanden?
191 SbxVariable* pRes = SbxObject::Find( rName, t );
192 if( !pRes && t != SbxCLASS_OBJECT )
194 // sonst suchen
195 Methods* p = m_pMethods;
196 short nIndex = 0;
197 BOOL bFound = FALSE;
198 while( p->nArgs != -1 )
200 if( rName.CompareIgnoreCaseToAscii( p->pName ) == COMPARE_EQUAL )
202 bFound = TRUE; break;
204 nIndex += ( p->nArgs & _ARGSMASK ) + 1;
205 p = m_pMethods + nIndex;
207 if( bFound )
209 // Args-Felder isolieren:
210 short nAccess = ( p->nArgs & _RWMASK ) >> 8;
211 short nType = ( p->nArgs & _TYPEMASK );
212 String aName( p->pName, RTL_TEXTENCODING_ASCII_US );
213 SbxClassType eCT = SbxCLASS_OBJECT;
214 if( nType & _PROPERTY )
215 eCT = SbxCLASS_PROPERTY;
216 else if( nType & _METHOD )
217 eCT = SbxCLASS_METHOD;
218 pRes = Make( aName, eCT, p->eType );
219 // Wir setzen den Array-Index + 1, da ja noch andere
220 // Standard-Properties existieren, die auch aktiviert
221 // werden muessen.
222 pRes->SetUserData( nIndex + 1 );
223 pRes->SetFlags( nAccess );
226 return pRes;
229 // Aktivierung eines Elements oder Anfordern eines Infoblocks
231 void CommunicationWrapper::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCT,
232 const SfxHint& rHint, const TypeId& rHT )
234 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
235 if( pHint )
237 SbxVariable* pVar = pHint->GetVar();
238 SbxArray* pPar = pVar->GetParameters();
239 USHORT nIndex = (USHORT) pVar->GetUserData();
240 // kein Index: weiterreichen!
241 if( nIndex )
243 ULONG t = pHint->GetId();
244 if( t == SBX_HINT_INFOWANTED )
245 pVar->SetInfo( GetInfo( (short) pVar->GetUserData() ) );
246 else
248 BOOL bWrite = FALSE;
249 if( t == SBX_HINT_DATACHANGED )
250 bWrite = TRUE;
251 if( t == SBX_HINT_DATAWANTED || bWrite )
253 // Parameter-Test fuer Methoden:
254 USHORT nPar = m_pMethods[ --nIndex ].nArgs & 0x00FF;
255 // Element 0 ist der Returnwert
256 if( ( !pPar && nPar )
257 || ( pPar && pPar->Count() != nPar+1 ) )
258 SetError( SbxERR_WRONG_ARGS );
259 // Alles klar, man kann den Call ausfuehren
260 else
262 (this->*(m_pMethods[ nIndex ].pFunc))( pVar, pPar, bWrite );
267 SbxObject::SFX_NOTIFY( rBC, rBCT, rHint, rHT );
271 // Zusammenbau der Infostruktur fuer einzelne Elemente
273 SbxInfo* CommunicationWrapper::GetInfo( short nIdx )
275 Methods* p = &m_pMethods[ nIdx ];
276 // Wenn mal eine Hilfedatei zur Verfuegung steht:
277 // SbxInfo* pInfo = new SbxInfo( Hilfedateiname, p->nHelpId );
278 SbxInfo* pRetInfo = new SbxInfo;
279 short nPar = p->nArgs & _ARGSMASK;
280 for( short i = 0; i < nPar; i++ )
282 p++;
283 String aName( p->pName, RTL_TEXTENCODING_ASCII_US );
284 USHORT nIFlags = ( p->nArgs >> 8 ) & 0x03;
285 if( p->nArgs & _OPT )
286 nIFlags |= SBX_OPTIONAL;
287 pRetInfo->AddParam( aName, p->eType, nIFlags );
289 return pRetInfo;
293 ////////////////////////////////////////////////////////////////////////////
295 // Hilfsmethoden für den Manager
297 IMPL_LINK( CommunicationWrapper, Open, CommunicationLink*, pLink )
299 if ( m_bCatchOpen )
300 m_pNewLink = pLink;
301 else
302 Events( CUniString("Open"), pLink );
303 return 1;
306 IMPL_LINK( CommunicationWrapper, Close, CommunicationLink*, pLink )
308 Events( CUniString("Close"), pLink );
309 return 1;
312 IMPL_LINK( CommunicationWrapper, Data, CommunicationLink*, pLink )
314 Events( CUniString("Data"), pLink );
315 return 1;
318 void CommunicationWrapper::Events( String aType, CommunicationLink* pLink )
320 if ( m_aEventHandlerName.Len() )
322 SbxArrayRef pPar = new SbxArray( SbxVARIANT );
323 pPar->Put( new SbxVariable( SbxSTRING ), 1 );
324 pPar->Get( 1 )->PutString( aType );
326 pPar->Put( new SbxVariable( SbxOBJECT ), 2 );
327 pPar->Get( 2 )->PutObject( new CommunicationWrapper( pLink ) );
329 Call( m_aEventHandlerName, pPar );
331 else
332 delete pLink->GetServiceData(); // Stream wegschmeissen um nicht zu blockieren
336 ////////////////////////////////////////////////////////////////////////////
338 // Properties und Methoden legen beim Get (bPut = FALSE) den Returnwert
339 // im Element 0 des Argv ab; beim Put (bPut = TRUE) wird der Wert aus
340 // Element 0 gespeichert.
342 // Die Methoden:
344 // Manager
345 void CommunicationWrapper::MStartCommunication( SbxVariable* pVar, SbxArray* pPar, BOOL /*bWrite*/ )
346 { // CommunicationLink StartCommunication( Host, Port )
347 m_bCatchOpen = TRUE;
348 if ( m_pManager->StartCommunication( ByteString( pPar->Get( 1 )->GetString(), RTL_TEXTENCODING_UTF8 ), pPar->Get( 2 )->GetULong() ) )
350 while ( !m_pNewLink )
351 GetpApp()->Reschedule();
352 m_bCatchOpen = FALSE;
353 CommunicationWrapper *pNewLinkWrapper = new CommunicationWrapper( m_pNewLink );
354 m_pNewLink = NULL;
355 pVar->PutObject( pNewLinkWrapper );
360 void CommunicationWrapper::MStopAllCommunication( SbxVariable* /*pVar*/, SbxArray* /*pPar*/, BOOL /*bWrite*/ )
361 { // StopAllCommunication // Alle Kommunikation wird abgebrochen
362 m_pManager->StopCommunication();
365 void CommunicationWrapper::MIsCommunicationRunning( SbxVariable* pVar, SbxArray* /*pPar*/, BOOL /*bWrite*/ )
366 { // BOOL IsCommunicationRunning // Läuft noch irgendwas
367 pVar->PutBool( m_pManager->IsCommunicationRunning() );
370 void CommunicationWrapper::MGetMyName( SbxVariable* pVar, SbxArray* /*pPar*/, BOOL /*bWrite*/ )
371 { // String GetMyName Der eigene Name
372 pVar->PutString( UniString( m_pManager->GetMyName( CM_FQDN ), RTL_TEXTENCODING_UTF8 ) );
375 void CommunicationWrapper::MIsLinkValid( SbxVariable* pVar, SbxArray* pPar, BOOL /*bWrite*/ )
376 { // BOOL IsLinkValid( CommunicationLink ) // Ist dieser Link noch gültig
377 CommunicationWrapper *pWrapper = (CommunicationWrapper*)(pPar->Get( 1 )->GetObject());
378 pVar->PutBool( m_pManager->IsLinkValid( pWrapper->GetCommunicationLink() ) );
381 void CommunicationWrapper::MSetCommunicationEventHandler( SbxVariable* /*pVar*/, SbxArray* pPar, BOOL /*bWrite*/ )
382 { // SetCommunicationEventHandler( String ) // Diese Funktion wird aufgerufen bei jedem Event
383 m_aEventHandlerName = pPar->Get( 1 )->GetString();
390 // Link
391 void CommunicationWrapper::LStopCommunication( SbxVariable* /*pVar*/, SbxArray* /*pPar*/, BOOL /*bWrite*/ )
392 { // StopCommunication Die Kommunikation wird abgebrochen
393 m_pLink->StopCommunication();
396 void CommunicationWrapper::LGetMyName( SbxVariable* pVar, SbxArray* /*pPar*/, BOOL /*bWrite*/ )
397 { // String GetMyName Der eigene Name
398 pVar->PutString( UniString( m_pLink->GetMyName( CM_FQDN ), RTL_TEXTENCODING_UTF8 ) );
401 void CommunicationWrapper::LGetHostName( SbxVariable* pVar, SbxArray* /*pPar*/, BOOL /*bWrite*/ )
402 { // String GetHostName Der Name des Anderen
403 pVar->PutString( UniString( m_pLink->GetCommunicationPartner( CM_FQDN ), RTL_TEXTENCODING_UTF8 ) );
406 void CommunicationWrapper::LSend( SbxVariable* /*pVar*/, SbxArray* pPar, BOOL /*bWrite*/ )
407 { // Send(String ) String an den Partner schicken
408 SvStream *pSendStream = m_pLink->GetBestCommunicationStream();
409 String aSendString = pPar->Get( 1 )->GetString();
410 pSendStream->WriteByteString( aSendString, RTL_TEXTENCODING_UTF8 );
411 m_pLink->TransferDataStream( pSendStream );
412 delete pSendStream;
415 void CommunicationWrapper::LGetString( SbxVariable* pVar, SbxArray* /*pPar*/, BOOL /*bWrite*/ )
416 { // String GetString Ergebnis des letzten Empfangs
417 SvStream *pReceiveStream = m_pLink->GetServiceData();
418 if ( pReceiveStream )
420 ULONG nLength = pReceiveStream->Seek( STREAM_SEEK_TO_END );
421 pReceiveStream->Seek( STREAM_SEEK_TO_BEGIN );
422 char *pBuffer = new char[nLength];
423 pReceiveStream->Read( pBuffer, nLength );
424 String aReceive(
425 pBuffer, sal::static_int_cast< xub_StrLen >( nLength ),
426 RTL_TEXTENCODING_UTF8 );
427 delete [] pBuffer;
428 pVar->PutString( aReceive );
429 delete pReceiveStream;
431 else
432 pVar->PutString( UniString() );
437 // Die Factory legt unser Objekte an.
439 SbxObject* CommunicationFactory::CreateObject( const String& rClass )
441 if( rClass.CompareIgnoreCaseToAscii( "CommunicationManager" ) == COMPARE_EQUAL )
442 return new CommunicationWrapper( rClass );
443 return NULL;