1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package mod._dbaccess;
29 
30 import java.io.PrintWriter;
31 import java.util.Vector;
32 
33 import lib.Status;
34 import lib.StatusException;
35 import lib.TestCase;
36 import lib.TestEnvironment;
37 import lib.TestParameters;
38 import util.DBTools;
39 import util.utils;
40 
41 import com.sun.star.beans.PropertyValue;
42 import com.sun.star.beans.XPropertySet;
43 import com.sun.star.lang.XComponent;
44 import com.sun.star.lang.XMultiServiceFactory;
45 import com.sun.star.sdb.CommandType;
46 import com.sun.star.sdb.ParametersRequest;
47 import com.sun.star.sdb.XInteractionSupplyParameters;
48 import com.sun.star.sdbc.XConnection;
49 import com.sun.star.sdbc.XResultSet;
50 import com.sun.star.sdbc.XResultSetUpdate;
51 import com.sun.star.sdbc.XRow;
52 import com.sun.star.sdbc.XRowSet;
53 import com.sun.star.sdbc.XRowUpdate;
54 import com.sun.star.task.XInteractionAbort;
55 import com.sun.star.task.XInteractionContinuation;
56 import com.sun.star.task.XInteractionRequest;
57 import com.sun.star.ucb.AuthenticationRequest;
58 import com.sun.star.uno.UnoRuntime;
59 import com.sun.star.uno.XInterface;
60 import com.sun.star.util.XCloseable;
61 import com.sun.star.frame.XModel;
62 import com.sun.star.sdb.RowChangeEvent;
63 import com.sun.star.sdbc.SQLException;
64 import com.sun.star.sdbc.XParameters;
65 import ifc.sdb._XCompletedExecution;
66 import util.db.DataSource;
67 import util.db.DataSourceDescriptor;
68 
69 /**
70  * Test for object which is represented by service
71  * <code>com.sun.star.sdb.RowSet</code>. <p>
72  *
73  * The following files used by this test :
74  * <ul>
75  *  <li><b> TestDB/TestDB.dbf </b> : the database file with some
76  *    predefined fields described in <code>util.DBTools</code>.
77  *    The copy of this file is always made in temp directory for
78  *    testing purposes.</li>
79  * </ul>
80  * The following parameters in ini-file used by this test:
81  * <ul>
82  *   <li><code>test.db.url</code> - URL to MySQL database.
83  *   For example: <code>mysql://mercury:3306/api_current</code></li>
84  *   <li><code>test.db.user</code> - user for MySQL database</li>
85  *   <li><code>test.db.password</code> - password for MySQL database</li>
86  * </ul>
87  *
88  * @see com.sun.star.sdbc.RowSet
89  * @see com.sun.star.sdbcx.XRowLocate
90  * @see com.sun.star.sdbc.XResultSetUpdate
91  * @see com.sun.star.util.XCancellable
92  * @see com.sun.star.sdbc.XParameters
93  * @see com.sun.star.sdbc.XResultSetMetaDataSupplier
94  * @see com.sun.star.sdbcx.XDeleteRows
95  * @see com.sun.star.sdbc.XCloseable
96  * @see com.sun.star.sdbcx.XColumnsSupplier
97  * @see com.sun.star.sdb.XResultSetAccess
98  * @see com.sun.star.sdbc.XResultSet
99  * @see com.sun.star.sdbc.XColumnLocate
100  * @see com.sun.star.sdbc.XRowSet
101  * @see com.sun.star.sdb.RowSet
102  * @see com.sun.star.sdbc.XRowUpdate
103  * @see com.sun.star.sdb.XRowSetApproveBroadcaster
104  * @see com.sun.star.beans.XPropertySet
105  * @see com.sun.star.sdbc.XRow
106  * @see com.sun.star.sdbc.XWarningsSupplier
107  * @see com.sun.star.lang.XComponent
108  * @see com.sun.star.sdbcx.ResultSet
109  * @see com.sun.star.sdbc.ResultSet
110  * @see ifc.sdbc._RowSet
111  * @see ifc.sdbcx._XRowLocate
112  * @see ifc.sdbc._XResultSetUpdate
113  * @see ifc.util._XCancellable
114  * @see ifc.sdbc._XParameters
115  * @see ifc.sdbc._XResultSetMetaDataSupplier
116  * @see ifc.sdbcx._XDeleteRows
117  * @see ifc.sdbc._XCloseable
118  * @see ifc.sdbcx._XColumnsSupplier
119  * @see ifc.sdb._XResultSetAccess
120  * @see ifc.sdbc._XResultSet
121  * @see ifc.sdbc._XColumnLocate
122  * @see ifc.sdbc._XRowSet
123  * @see ifc.sdb._RowSet
124  * @see ifc.sdbc._XRowUpdate
125  * @see ifc.sdb._XRowSetApproveBroadcaster
126  * @see ifc.beans._XPropertySet
127  * @see ifc.sdbc._XRow
128  * @see ifc.sdbc._XWarningsSupplier
129  * @see ifc.lang._XComponent
130  * @see ifc.sdbcx._ResultSet
131  * @see ifc.sdbc._ResultSet
132  */
133 public class ORowSet extends TestCase {
134 
135     private static int uniqueSuffix = 0 ;
136     private DBTools dbTools     = null ;
137     private static String origDB = null ;
138     String tableName = null;
139     DataSourceDescriptor srcInf = null;
140     boolean isMySQLDB = false;
141     protected final static String dbSourceName = "ORowSetDataSource";
142     public XConnection m_connection = null;
143     private Object m_rowSet = null;
144     private DataSource m_dataSource;
145     private String m_tableFile;
146     private XMultiServiceFactory m_orb = null;
147 
148     /**
149     * Initializes some class fields. Then creates DataSource, which serves
150     * as a single source for all tables created in the test.
151     * This DataSource then registered in the global
152     * <code>DatabaseContext</code> service. This data source's URL
153     * points to SOffice temp directory where tables are copied from
154     * <code>TestDocuments</code> directory on every environment
155     * creation.
156     * To create DataSource for MySQL database next parameters required
157     * in ini-file:
158     * <ul>
159     *   <li><code>test.db.url</code> - URL to MySQL database.
160     *   For example: <code>mysql://mercury:3306/api_current</code></li>
161     *   <li><code>test.db.user</code> - user for MySQL database</li>
162     *   <li><code>test.db.password</code> - password for MySQL database</li>
163     * </ul>
164     *
165     * @throws StatusException if DataSource can not be created or
166     * registered.
167     */
168     protected void initialize ( TestParameters Param, PrintWriter _log)
169         throws StatusException
170     {
171         m_orb = (XMultiServiceFactory)Param.getMSF();
172 
173         String tmpDir = utils.getOfficeTemp( m_orb );
174 
175         origDB = util.utils.getFullTestDocName("TestDB/testDB.dbf");
176 
177         dbTools = new DBTools( m_orb, _log );
178 
179         // creating DataSource and registering it in DatabaseContext
180         String dbURL = (String) Param.get("test.db.url");
181         String dbUser = (String) Param.get("test.db.user");
182         String dbPassword = (String) Param.get("test.db.password");
183 
184         log.println("Creating and registering DataSource ...");
185         srcInf = new DataSourceDescriptor( m_orb );
186         if (dbURL != null && dbUser != null && dbPassword != null)
187         {
188             isMySQLDB = true;
189             log.println("dbURL = " + dbURL);
190             log.println("dbUSER = " + dbUser);
191             log.println("dbPASSWORD = " + dbPassword);
192             //DataSource for mysql db
193             tableName = "soffice_test_table";
194             srcInf.URL = "jdbc:" + dbURL;
195             srcInf.IsPasswordRequired = new Boolean(true);
196             srcInf.Password = dbPassword;
197             srcInf.User = dbUser;
198             PropertyValue[] propInfo = new PropertyValue[1];
199             propInfo[0] = new PropertyValue();
200             propInfo[0].Name = "JavaDriverClass";
201             propInfo[0].Value = "org.gjt.mm.mysql.Driver";
202             srcInf.Info = propInfo;
203         }
204         else
205         {
206             srcInf.URL = "sdbc:dbase:" + DBTools.dirToUrl(tmpDir);
207         }
208         m_dataSource = srcInf.createDataSource();
209         m_dataSource.registerAs( dbSourceName, true );
210     }
211 
212     /**
213     * Creating a Testenvironment for the interfaces to be tested.
214     * The database (DBF) file is copied from test document directory
215     * into SOffice temp dir with unique name for each enviroment
216     * creation. If the file cann't be copied (is not released)
217     * then another unique name is used (file name suffix incremented
218     * by 1).<p>
219     *
220     * <code>com.sun.star.sdb.RowSet</code> service created and its
221     * source is all rows from the current copy of the table. Then
222     * row set command ("select all rows from a table") is executed
223     * and cursor is positioned to the first row. <p>
224     *
225     *     Object relations created :
226     * <ul>
227     *  <li> <code>'ORowSet.Connection'</code> for
228     *      internal component test usage. Is used for
229     *      closing connection when cleaning up environment. </li>
230     *  <li> <code>'XRowSetApproveBroadcaster.ApproveChecker'</code> for
231     *      {@link ifc.sdb._XRowSetApproveBroadcaster} interface
232     *      implementation which made actions required </li>
233     *  <li> <code>'CurrentRowData'</code> for
234     *      {@link ifc.sdbc._XRow}, {@link ifc.sdbc._XRowUpdate} :
235     *      exports types and values of the current row data.</li>
236     *  <li> <code>'XColumnLocate.ColumnName'</code> for
237     *      {@link ifc.sdbc._XColumnLocate} :
238     *      the name of the first column of the table.</li>
239     *  <li> <code>'XParameters.ParamValues'</code> for
240     *      {@link ifc.sdbc._XParameters} :
241     *      Collection of parameter types presented in the query. </li>
242     *  <li> <code>'XRowUpdate.XRow'</code> for
243     *      {@link ifc.sdbc._XRowUpdate} :
244     *      <code>XRow</code> interface of the current component.</li>
245     *  <li> <code>'XResultSetUpdate.UpdateTester'</code> for
246     *      {@link ifc.sdbc._XResultSetUpdate} </li>
247     * </ul>
248     *
249     * @see com.sun.star.sdb.DatabaseContext
250     * @see com.sun.star.sdb.DataSource
251     */
252     protected TestEnvironment createTestEnvironment(TestParameters Param,
253             PrintWriter log)
254     {
255         XMultiServiceFactory orb = (XMultiServiceFactory)Param.getMSF();
256         uniqueSuffix++;
257         boolean envCreatedOK = false ;
258 
259         //initialize test table
260         if (isMySQLDB)
261         {
262             try
263             {
264                 DBTools.DataSourceInfo legacyDescriptor = dbTools.newDataSourceInfo();
265                 legacyDescriptor.Name = srcInf.Name;
266                 legacyDescriptor.User = srcInf.User;
267                 legacyDescriptor.Password = srcInf.Password;
268                 legacyDescriptor.Info = srcInf.Info;
269                 legacyDescriptor.URL = srcInf.URL;
270                 legacyDescriptor.IsPasswordRequired = srcInf.IsPasswordRequired;
271                 dbTools.initTestTableUsingJDBC(tableName, legacyDescriptor);
272             }
273             catch(java.sql.SQLException e)
274             {
275                 e.printStackTrace(log);
276                 throw new StatusException(Status.failed("Couldn't " +
277                     " init test table. SQLException..."));
278             }
279             catch(java.lang.ClassNotFoundException e)
280             {
281                 throw new StatusException(Status.failed("Couldn't " +
282                     "register mysql driver"));
283             }
284         }
285         else
286         {
287             String oldF = null ;
288             String newF = null ;
289             String tempFolder = utils.getOfficeTemp( orb );
290             do
291             {
292                 tableName = "ORowSet_tmp" + uniqueSuffix ;
293                 oldF = utils.getFullURL(origDB);
294                 newF = tempFolder + tableName + ".dbf";
295             }
296             while ( !utils.tryOverwriteFile( orb, oldF, newF ) );
297             m_tableFile = newF;
298         }
299 
300         try
301         {
302             m_rowSet = orb.createInstance("com.sun.star.sdb.RowSet");
303 
304             XPropertySet rowSetProps = UnoRuntime.queryInterface( XPropertySet.class, m_rowSet );
305 
306             log.println("Trying to open: " + tableName);
307 
308             rowSetProps.setPropertyValue("DataSourceName", dbSourceName);
309             rowSetProps.setPropertyValue("Command", tableName);
310             rowSetProps.setPropertyValue("CommandType",
311                 new Integer(CommandType.TABLE));
312 
313             final XRowSet rowSet = UnoRuntime.queryInterface( XRowSet.class, m_rowSet);
314             rowSet.execute();
315             m_connection = UnoRuntime.queryInterface( XConnection.class, rowSetProps.getPropertyValue("ActiveConnection") );
316 
317             XResultSet xRes = UnoRuntime.queryInterface( XResultSet.class, m_rowSet );
318             xRes.first();
319 
320             log.println( "creating a new environment for object" );
321             TestEnvironment tEnv = new TestEnvironment( (XInterface)m_rowSet );
322 
323             // Adding obj relation for XRowSetApproveBroadcaster test
324             {
325                 final XResultSet resultSet = UnoRuntime.queryInterface( XResultSet.class, m_rowSet );
326                 final XResultSetUpdate resultSetUpdate = UnoRuntime.queryInterface( XResultSetUpdate.class, m_rowSet );
327                 final XRowUpdate rowUpdate = UnoRuntime.queryInterface(XRowUpdate.class, m_rowSet );
328                 final PrintWriter logF = log ;
329                 tEnv.addObjRelation( "XRowSetApproveBroadcaster.ApproveChecker",
330                     new ifc.sdb._XRowSetApproveBroadcaster.RowSetApproveChecker()
331                     {
332                         public void moveCursor()
333                         {
334                             try
335                             {
336                                 resultSet.beforeFirst();
337                                 resultSet.afterLast();
338                                 resultSet.first();
339                             }
340                             catch (com.sun.star.sdbc.SQLException e)
341                             {
342                                 logF.println("### _XRowSetApproveBroadcaster.RowSetApproveChecker.moveCursor() :");
343                                 e.printStackTrace(logF);
344                                 throw new StatusException( "RowSetApproveChecker.moveCursor failed", e );
345                             }
346                         }
347                         public RowChangeEvent changeRow()
348                         {
349                             try
350                             {
351                                 resultSet.first();
352                                 rowUpdate.updateString(1, "ORowSetTest2");
353                                 resultSetUpdate.updateRow();
354                             }
355                             catch (com.sun.star.sdbc.SQLException e)
356                             {
357                                 logF.println("### _XRowSetApproveBroadcaster.RowSetApproveChecker.changeRow() :");
358                                 e.printStackTrace(logF);
359                                 throw new StatusException( "RowSetApproveChecker.changeRow failed", e );
360                             }
361                             RowChangeEvent ev = new RowChangeEvent();
362                             ev.Action = com.sun.star.sdb.RowChangeAction.UPDATE ;
363                             ev.Rows = 1 ;
364 
365                             return ev ;
366                         }
367                         public void changeRowSet()
368                         {
369                             try
370                             {
371                                 // since we gave the row set a parametrized statement, we need to ensure the
372                                 // parameter is actually filled, otherwise we would get an empty result set,
373                                 // which would imply some further tests failing
374                                 XParameters rowSetParams = UnoRuntime.queryInterface( XParameters.class, resultSet );
375                                 rowSetParams.setString( 1, "String2" );
376                                 rowSet.execute();
377                                 resultSet.first();
378                             }
379                             catch (com.sun.star.sdbc.SQLException e)
380                             {
381                                 logF.println("### _XRowSetApproveBroadcaster.RowSetApproveChecker.changeRowSet() :");
382                                 e.printStackTrace(logF);
383                                 throw new StatusException( "RowSetApproveChecker.changeRowSet failed", e );
384                             }
385                         }
386                     }
387                 );
388             }
389             // Adding relations for XRow as a Vector with all data
390             // of current row of RowSet.
391 
392             Vector rowData = new Vector();
393 
394             for (int i = 0; i < DBTools.TST_TABLE_VALUES[0].length; i++) {
395                 rowData.add(DBTools.TST_TABLE_VALUES[0][i]);
396             }
397 
398             // here XRef must be added
399             // here XBlob must be added
400             // here XClob must be added
401             // here XArray must be added
402 
403             tEnv.addObjRelation("CurrentRowData", rowData);
404 
405             // Adding relation for XColumnLocate ifc test
406             tEnv.addObjRelation( "XColumnLocate.ColumnName", DBTools.TST_STRING_F );
407 
408             // Adding relation for XCompletedExecution
409             tEnv.addObjRelation( "InteractionHandlerChecker", new InteractionHandlerImpl() );
410             try
411             {
412                 String sqlCommand = isMySQLDB
413                     ?   "SELECT Column0  FROM soffice_test_table  WHERE ( (  Column0 = :param1 ) )"
414                     :   "SELECT \"_TEXT\" FROM \"" + tableName + "\" WHERE ( ( \"_TEXT\" = :param1 ) )";
415                 rowSetProps.setPropertyValue( "DataSourceName", dbSourceName );
416                 rowSetProps.setPropertyValue( "Command", sqlCommand );
417                 rowSetProps.setPropertyValue( "CommandType", new Integer(CommandType.COMMAND) );
418             }
419             catch(Exception e)
420             {
421                 throw new StatusException( "setting up the RowSet with a parametrized command failed", e );
422             }
423 
424             // Adding relation for XParameters ifc test
425             tEnv.addObjRelation( "XParameters.ParamValues", new Vector() );
426 
427             // Adding relation for XRowUpdate
428             final XRow row = UnoRuntime.queryInterface( XRow.class, m_rowSet );
429             tEnv.addObjRelation("XRowUpdate.XRow", row);
430 
431             // Adding relation for XResultSetUpdate
432             {
433                 final XResultSet resultSet = UnoRuntime.queryInterface( XResultSet.class, m_rowSet );
434                 final XRowUpdate rowUpdate = UnoRuntime.queryInterface( XRowUpdate.class, m_rowSet );
435 
436                 tEnv.addObjRelation("XResultSetUpdate.UpdateTester",
437                     new ifc.sdbc._XResultSetUpdate.UpdateTester()
438                     {
439                         String lastUpdate = null ;
440 
441                         public int rowCount() throws SQLException
442                         {
443                             int prevPos = resultSet.getRow();
444                             resultSet.last();
445                             int count = resultSet.getRow();
446                             resultSet.absolute(prevPos);
447 
448                             return count ;
449                         }
450 
451                         public void update() throws SQLException
452                         {
453                             lastUpdate = row.getString(1);
454                             lastUpdate += "_" ;
455                             rowUpdate.updateString(1, lastUpdate);
456                         }
457 
458                         public boolean wasUpdated() throws SQLException
459                         {
460                             String getStr = row.getString(1);
461                             return lastUpdate.equals(getStr);
462                         }
463 
464                         public int currentRow() throws SQLException
465                         {
466                             return resultSet.getRow();
467                         }
468                     }
469                 );
470             }
471 
472             envCreatedOK = true ;
473             return tEnv;
474 
475         }
476         catch(com.sun.star.uno.Exception e)
477         {
478             log.println( "couldn't set up tes tenvironment:" );
479             e.printStackTrace(log);
480             try
481             {
482                 if ( m_connection != null )
483                     m_connection.close();
484             }
485             catch(Exception ex)
486             {
487             }
488             throw new StatusException( "couldn't set up tes tenvironment", e );
489         }
490         finally
491         {
492             if (!envCreatedOK)
493             {
494                 try
495                 {
496                     m_connection.close();
497                 }
498                 catch(Exception ex)
499                 {
500                 }
501             }
502         }
503 
504     } // finish method getTestEnvironment
505 
506     /**
507     * Closes connection of <code>RowSet</code> instance created.
508     */
509     protected void cleanup( TestParameters Param, PrintWriter log)
510     {
511         String doing = null;
512         try
513         {
514             doing = "revoking data source registration";
515             log.println( doing );
516             m_dataSource.revokeRegistration();
517 
518             doing = "closing database document";
519             log.println( doing );
520             XModel databaseDocModel = UnoRuntime.queryInterface( XModel.class,
521                 m_dataSource.getDatabaseDocument().getDatabaseDocument() );
522             String documentFile = databaseDocModel.getURL();
523 
524             XCloseable closeModel = UnoRuntime.queryInterface( XCloseable.class,
525                 m_dataSource.getDatabaseDocument().getDatabaseDocument() );
526             closeModel.close( true );
527 
528             if ( m_rowSet != null )
529             {
530                 doing = "disposing row set";
531                 log.println( doing );
532                 XComponent rowSetComponent = UnoRuntime.queryInterface( XComponent.class, m_rowSet );
533                 rowSetComponent.dispose();
534             }
535 
536             try
537             {
538                 doing = "closing connection";
539                 log.println( doing );
540                 m_connection.close();
541             }
542             catch (com.sun.star.lang.DisposedException e)
543             {
544                 log.println( "already closed - okay." );
545             }
546 
547             doing = "deleting database file ("  + documentFile + ")";
548             log.println( doing );
549             impl_deleteFile( documentFile );
550 
551             if ( m_tableFile != null )
552             {
553                 doing = "deleting dBase table file (" + m_tableFile + ")";
554                 log.println( doing );
555                 impl_deleteFile( m_tableFile );
556             }
557         }
558         catch (com.sun.star.uno.Exception e)
559         {
560             log.println( "error: ");
561             e.printStackTrace(log);
562         }
563     }
564 
565     private final void impl_deleteFile( final String _file )
566     {
567         java.io.File file = new java.io.File( _file );
568         file.delete();
569         if ( file.exists() )
570             file.deleteOnExit();
571     }
572 
573     /**
574      * Implementation of interface _XCompletedExecution.CheckInteractionHandler
575      * for the XCompletedExecution test
576      * @see ifc.sdb._XCompletedExecution
577      */
578     public class InteractionHandlerImpl implements _XCompletedExecution.CheckInteractionHandler {
579         private boolean handlerWasUsed = false;
580         private PrintWriter log = new PrintWriter(System.out);
581 
582         public boolean checkInteractionHandler() {
583             return handlerWasUsed;
584         }
585 
586         public void handle(XInteractionRequest xInteractionRequest) {
587             log.println("### _XCompletedExecution.InteractionHandlerImpl: handle called.");
588             ParametersRequest req = null;
589             boolean abort = false;
590 
591             Object o = xInteractionRequest.getRequest();
592             if (o instanceof ParametersRequest) {
593                 req = (ParametersRequest)o;
594             }
595             else if (o instanceof AuthenticationRequest) {
596                 log.println("### The request in XCompletedExecution is of type 'AuthenticationRequest'");
597                 log.println("### This is not implemented in ORowSet.InteractionHandlerImpl test -> abort.");
598                 abort = true;
599             }
600             else {
601                 log.println("### Unknown request:" + o.toString());
602                 log.println("### This is not implemented in ORowSet.InteractionHandlerImpl test -> abort.");
603                 abort = true;
604             }
605 
606             XInteractionContinuation[]xCont = xInteractionRequest.getContinuations();
607             XInteractionSupplyParameters xParamCallback = null;
608             for(int i=0; i<xCont.length; i++) {
609                 if (abort) {
610                     XInteractionAbort xAbort = null;
611                     xAbort = UnoRuntime.queryInterface(XInteractionAbort.class, xCont[i]);
612                     if (xAbort != null)
613                         xAbort.select();
614                         return;
615                 }
616                 else {
617                     xParamCallback = UnoRuntime.queryInterface(XInteractionSupplyParameters.class, xCont[i]);
618                     if (xParamCallback != null)
619                         break;
620                 }
621             }
622             if (xParamCallback != null) {
623                 log.println("### _XCompletedExecution.InteractionHandlerImpl: supplying parameters.");
624                 handlerWasUsed = true;
625                 PropertyValue[] prop = new PropertyValue[1];
626                 prop[0] = new PropertyValue();
627                 prop[0].Name = "param1";
628                 prop[0].Value = "Hi.";
629 
630                 xParamCallback.setParameters(prop);
631                 xParamCallback.select();
632             }
633             else { // we should never reach this: abort has to be true first.
634                 log.println("### _XCompletedExecution.InteractionHandlerImpl: Got no " +
635                             "'XInteractionSupplyParameters' and no 'XInteractionAbort'.");
636             }
637         }
638 
639         public void setLog(PrintWriter log) {
640             this.log = log;
641         }
642 
643     }
644 }
645