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