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