View Javadoc
1 package org.apache.torque.task; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001-2003 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Turbine" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache Turbine", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>. 55 */ 56 57 import java.io.BufferedOutputStream; 58 import java.io.BufferedReader; 59 import java.io.IOException; 60 import java.io.InputStreamReader; 61 import java.io.File; 62 import java.io.FileInputStream; 63 import java.io.FileOutputStream; 64 import java.io.FileReader; 65 import java.io.PrintStream; 66 import java.io.StringReader; 67 import java.io.Reader; 68 import java.util.List; 69 import java.util.ArrayList; 70 import java.util.Iterator; 71 import java.util.HashMap; 72 import java.util.Map; 73 import java.util.Properties; 74 import java.sql.Connection; 75 import java.sql.DatabaseMetaData; 76 import java.sql.Driver; 77 import java.sql.ResultSet; 78 import java.sql.ResultSetMetaData; 79 import java.sql.SQLException; 80 import java.sql.SQLWarning; 81 import java.sql.Statement; 82 import org.apache.commons.lang.StringUtils; 83 import org.apache.tools.ant.AntClassLoader; 84 import org.apache.tools.ant.BuildException; 85 import org.apache.tools.ant.Project; 86 import org.apache.tools.ant.ProjectHelper; 87 import org.apache.tools.ant.Task; 88 import org.apache.tools.ant.types.EnumeratedAttribute; 89 import org.apache.tools.ant.types.Path; 90 import org.apache.tools.ant.types.Reference; 91 92 /*** 93 * This task uses an SQL -> Database map in the form of a properties 94 * file to insert each SQL file listed into its designated database. 95 * 96 * @author <a href="mailto:jeff@custommonkey.org">Jeff Martin</a> 97 * @author <a href="mailto:gholam@xtra.co.nz">Michael McCallum</A> 98 * @author <a href="mailto:tim.stephenson@sybase.com">Tim Stephenson</A> 99 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</A> 100 * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a> 101 * @version $Id: TorqueSQLExec.java,v 1.2 2003/03/21 17:31:08 mpoeschl Exp $ 102 */ 103 public class TorqueSQLExec extends Task 104 { 105 private int goodSql = 0; 106 private int totalSql = 0; 107 private Path classpath; 108 private AntClassLoader loader; 109 110 /*** 111 * 112 */ 113 public static class DelimiterType extends EnumeratedAttribute 114 { 115 public static final String NORMAL = "normal"; 116 public static final String ROW = "row"; 117 118 public String[] getValues() 119 { 120 return new String[] {NORMAL, ROW}; 121 } 122 } 123 124 /*** Database connection */ 125 private Connection conn = null; 126 127 /*** Autocommit flag. Default value is false */ 128 private boolean autocommit = false; 129 130 /*** SQL statement */ 131 private Statement statement = null; 132 133 /*** DB driver. */ 134 private String driver = null; 135 136 /*** DB url. */ 137 private String url = null; 138 139 /*** User name. */ 140 private String userId = null; 141 142 /*** Password */ 143 private String password = null; 144 145 /*** SQL input command */ 146 private String sqlCommand = ""; 147 148 /*** SQL Statement delimiter */ 149 private String delimiter = ";"; 150 151 /*** 152 * The delimiter type indicating whether the delimiter will 153 * only be recognized on a line by itself 154 */ 155 private String delimiterType = DelimiterType.NORMAL; 156 157 /*** Print SQL results. */ 158 private boolean print = false; 159 160 /*** Print header columns. */ 161 private boolean showheaders = true; 162 163 /*** Results Output file. */ 164 private File output = null; 165 166 /*** RDBMS Product needed for this SQL. */ 167 private String rdbms = null; 168 169 /*** RDBMS Version needed for this SQL. */ 170 private String version = null; 171 172 /*** Action to perform if an error is found */ 173 private String onError = "abort"; 174 175 /*** Encoding to use when reading SQL statements from a file */ 176 private String encoding = null; 177 178 /*** Src directory for the files listed in the sqldbmap. */ 179 private String srcDir; 180 181 /*** Properties file that maps an individual SQL file to a database. */ 182 private File sqldbmap; 183 184 /*** 185 * Set the sqldbmap properties file. 186 * 187 * @param sqldbmap filename for the sqldbmap 188 */ 189 public void setSqlDbMap(String sqldbmap) 190 { 191 this.sqldbmap = project.resolveFile(sqldbmap); 192 } 193 194 /*** 195 * Get the sqldbmap properties file. 196 * 197 * @return filename for the sqldbmap 198 */ 199 public File getSqlDbMap() 200 { 201 return sqldbmap; 202 } 203 204 /*** 205 * Set the src directory for the sql files listed in the sqldbmap file. 206 * 207 * @param srcDir sql source directory 208 */ 209 public void setSrcDir(String srcDir) 210 { 211 this.srcDir = project.resolveFile(srcDir).toString(); 212 } 213 214 /*** 215 * Get the src directory for the sql files listed in the sqldbmap file. 216 * 217 * @return sql source directory 218 */ 219 public String getSrcDir() 220 { 221 return srcDir; 222 } 223 224 /*** 225 * Set the classpath for loading the driver. 226 * 227 * @param classpath the classpath 228 */ 229 public void setClasspath(Path classpath) 230 { 231 if (this.classpath == null) 232 { 233 this.classpath = classpath; 234 } 235 else 236 { 237 this.classpath.append(classpath); 238 } 239 } 240 241 /*** 242 * Create the classpath for loading the driver. 243 * 244 * @return the classpath 245 */ 246 public Path createClasspath() 247 { 248 if (this.classpath == null) 249 { 250 this.classpath = new Path(project); 251 } 252 return this.classpath.createPath(); 253 } 254 255 /*** 256 * Set the classpath for loading the driver using the classpath reference. 257 * 258 * @param r reference to the classpath 259 */ 260 public void setClasspathRef(Reference r) 261 { 262 createClasspath().setRefid(r); 263 } 264 265 /*** 266 * Set the sql command to execute 267 * 268 * @param sql sql command to execute 269 */ 270 public void addText(String sql) 271 { 272 this.sqlCommand += sql; 273 } 274 275 /*** 276 * Set the JDBC driver to be used. 277 * 278 * @param driver driver class name 279 */ 280 public void setDriver(String driver) 281 { 282 this.driver = driver; 283 } 284 285 /*** 286 * Set the DB connection url. 287 * 288 * @param url connection url 289 */ 290 public void setUrl(String url) 291 { 292 this.url = url; 293 } 294 295 /*** 296 * Set the user name for the DB connection. 297 * 298 * @param userId database user 299 */ 300 public void setUserid(String userId) 301 { 302 this.userId = userId; 303 } 304 305 /*** 306 * Set the file encoding to use on the sql files read in 307 * 308 * @param encoding the encoding to use on the files 309 */ 310 public void setEncoding(String encoding) 311 { 312 this.encoding = encoding; 313 } 314 315 /*** 316 * Set the password for the DB connection. 317 * 318 * @param password database password 319 */ 320 public void setPassword(String password) 321 { 322 this.password = password; 323 } 324 325 /*** 326 * Set the autocommit flag for the DB connection. 327 * 328 * @param autocommit the autocommit flag 329 */ 330 public void setAutocommit(boolean autocommit) 331 { 332 this.autocommit = autocommit; 333 } 334 335 /*** 336 * Set the statement delimiter. 337 * 338 * <p>For example, set this to "go" and delimitertype to "ROW" for 339 * Sybase ASE or MS SQL Server.</p> 340 * 341 * @param delimiter 342 */ 343 public void setDelimiter(String delimiter) 344 { 345 this.delimiter = delimiter; 346 } 347 348 /*** 349 * Set the Delimiter type for this sql task. The delimiter type takes two 350 * values - normal and row. Normal means that any occurence of the delimiter 351 * terminate the SQL command whereas with row, only a line containing just 352 * the delimiter is recognized as the end of the command. 353 * 354 * @param delimiterType 355 */ 356 public void setDelimiterType(DelimiterType delimiterType) 357 { 358 this.delimiterType = delimiterType.getValue(); 359 } 360 361 /*** 362 * Set the print flag. 363 * 364 * @param print 365 */ 366 public void setPrint(boolean print) 367 { 368 this.print = print; 369 } 370 371 /*** 372 * Set the showheaders flag. 373 * 374 * @param showheaders 375 */ 376 public void setShowheaders(boolean showheaders) 377 { 378 this.showheaders = showheaders; 379 } 380 381 /*** 382 * Set the output file. 383 * 384 * @param output 385 */ 386 public void setOutput(File output) 387 { 388 this.output = output; 389 } 390 391 /*** 392 * Set the rdbms required 393 * 394 * @param vendor 395 */ 396 public void setRdbms(String vendor) 397 { 398 this.rdbms = vendor.toLowerCase(); 399 } 400 401 /*** 402 * Set the version required 403 * 404 * @param version 405 */ 406 public void setVersion(String version) 407 { 408 this.version = version.toLowerCase(); 409 } 410 411 /*** 412 * Set the action to perform onerror 413 * 414 * @param action 415 */ 416 public void setOnerror(OnError action) 417 { 418 this.onError = action.getValue(); 419 } 420 421 /*** 422 * Load the sql file and then execute it 423 * 424 * @throws BuildException 425 */ 426 public void execute() throws BuildException 427 { 428 sqlCommand = sqlCommand.trim(); 429 430 if (sqldbmap == null || getSqlDbMap().exists() == false) 431 { 432 throw new BuildException("You haven't provided an sqldbmap, or " 433 + "the one you specified doesn't exist: " + sqldbmap); 434 } 435 436 if (driver == null) 437 { 438 throw new BuildException("Driver attribute must be set!", location); 439 } 440 if (userId == null) 441 { 442 throw new BuildException("User Id attribute must be set!", 443 location); 444 } 445 if (password == null) 446 { 447 throw new BuildException("Password attribute must be set!", 448 location); 449 } 450 if (url == null) 451 { 452 throw new BuildException("Url attribute must be set!", location); 453 } 454 455 Properties map = new Properties(); 456 457 try 458 { 459 FileInputStream fis = new FileInputStream(getSqlDbMap()); 460 map.load(fis); 461 fis.close(); 462 } 463 catch (IOException ioe) 464 { 465 throw new BuildException("Cannot open and process the sqldbmap!"); 466 } 467 468 Map databases = new HashMap(); 469 470 Iterator eachFileName = map.keySet().iterator(); 471 while (eachFileName.hasNext()) 472 { 473 String sqlfile = (String) eachFileName.next(); 474 String database = map.getProperty(sqlfile); 475 476 List files = (List) databases.get(database); 477 478 if (files == null) 479 { 480 files = new ArrayList(); 481 databases.put(database, files); 482 } 483 484 // We want to make sure that the base schemas 485 // are inserted first. 486 if (sqlfile.indexOf("schema.sql") != -1) 487 { 488 files.add(0, sqlfile); 489 } 490 else 491 { 492 files.add(sqlfile); 493 } 494 } 495 496 Iterator eachDatabase = databases.keySet().iterator(); 497 while (eachDatabase.hasNext()) 498 { 499 String db = (String) eachDatabase.next(); 500 List transactions = new ArrayList(); 501 eachFileName = ((List) databases.get(db)).iterator(); 502 while (eachFileName.hasNext()) 503 { 504 String fileName = (String) eachFileName.next(); 505 File file = new File(srcDir, fileName); 506 507 if (file.exists()) 508 { 509 Transaction transaction = new Transaction(); 510 transaction.setSrc(file); 511 transactions.add(transaction); 512 } 513 else 514 { 515 super.log("File '" + fileName 516 + "' in sqldbmap does not exist, so skipping it."); 517 } 518 } 519 520 insertDatabaseSqlFiles(url, db, transactions); 521 } 522 } 523 524 /*** 525 * Take the base url, the target database and insert a set of SQL 526 * files into the target database. 527 * 528 * @param url 529 * @param database 530 * @param transactions 531 */ 532 private void insertDatabaseSqlFiles(String url, String database, 533 List transactions) 534 { 535 url = StringUtils.replace(url, "@DB@", database); 536 System.out.println("Our new url -> " + url); 537 538 Driver driverInstance = null; 539 try 540 { 541 Class dc; 542 if (classpath != null) 543 { 544 log("Loading " + driver 545 + " using AntClassLoader with classpath " + classpath, 546 Project.MSG_VERBOSE); 547 548 loader = new AntClassLoader(project, classpath); 549 dc = loader.loadClass(driver); 550 } 551 else 552 { 553 log("Loading " + driver + " using system loader.", 554 Project.MSG_VERBOSE); 555 dc = Class.forName(driver); 556 } 557 driverInstance = (Driver) dc.newInstance(); 558 } 559 catch (ClassNotFoundException e) 560 { 561 throw new BuildException("Class Not Found: JDBC driver " + driver 562 + " could not be loaded", location); 563 } 564 catch (IllegalAccessException e) 565 { 566 throw new BuildException("Illegal Access: JDBC driver " + driver 567 + " could not be loaded", location); 568 } 569 catch (InstantiationException e) 570 { 571 throw new BuildException("Instantiation Exception: JDBC driver " 572 + driver + " could not be loaded", location); 573 } 574 575 try 576 { 577 log("connecting to " + url, Project.MSG_VERBOSE); 578 Properties info = new Properties(); 579 info.put("user", userId); 580 info.put("password", password); 581 conn = driverInstance.connect(url, info); 582 583 if (conn == null) 584 { 585 // Driver doesn't understand the URL 586 throw new SQLException("No suitable Driver for " + url); 587 } 588 589 if (!isValidRdbms(conn)) 590 { 591 return; 592 } 593 594 conn.setAutoCommit(autocommit); 595 statement = conn.createStatement(); 596 PrintStream out = System.out; 597 try 598 { 599 if (output != null) 600 { 601 log("Opening PrintStream to output file " + output, 602 Project.MSG_VERBOSE); 603 out = new PrintStream(new BufferedOutputStream( 604 new FileOutputStream(output))); 605 } 606 607 // Process all transactions 608 for (Iterator it = transactions.iterator(); it.hasNext();) 609 { 610 ((Transaction) it.next()).runTransaction(out); 611 if (!autocommit) 612 { 613 log("Commiting transaction", Project.MSG_VERBOSE); 614 conn.commit(); 615 } 616 } 617 } 618 finally 619 { 620 if (out != null && out != System.out) 621 { 622 out.close(); 623 } 624 } 625 } 626 catch (IOException e) 627 { 628 if (!autocommit && conn != null && onError.equals("abort")) 629 { 630 try 631 { 632 conn.rollback(); 633 } 634 catch (SQLException ex) 635 { 636 // do nothing. 637 } 638 } 639 throw new BuildException(e, location); 640 } 641 catch (SQLException e) 642 { 643 if (!autocommit && conn != null && onError.equals("abort")) 644 { 645 try 646 { 647 conn.rollback(); 648 } 649 catch (SQLException ex) 650 { 651 // do nothing. 652 } 653 } 654 throw new BuildException(e, location); 655 } 656 finally 657 { 658 try 659 { 660 if (statement != null) 661 { 662 statement.close(); 663 } 664 if (conn != null) 665 { 666 conn.close(); 667 } 668 } 669 catch (SQLException e) 670 { 671 } 672 } 673 674 log(goodSql + " of " + totalSql 675 + " SQL statements executed successfully"); 676 } 677 678 /*** 679 * Read the statements from the .sql file and execute them. 680 * Lines starting with '//', '--' or 'REM ' are ignored. 681 * 682 * @param reader 683 * @param out 684 * @throws SQLException 685 * @throws IOException 686 */ 687 protected void runStatements(Reader reader, PrintStream out) 688 throws SQLException, IOException 689 { 690 String sql = ""; 691 String line = ""; 692 693 BufferedReader in = new BufferedReader(reader); 694 695 try 696 { 697 while ((line = in.readLine()) != null) 698 { 699 line = line.trim(); 700 line = ProjectHelper.replaceProperties(project, line, 701 project.getProperties()); 702 if (line.startsWith("//") || line.startsWith("--")) 703 { 704 continue; 705 } 706 if (line.length() > 4 707 && line.substring(0, 4).equalsIgnoreCase("REM ")) 708 { 709 continue; 710 } 711 712 sql += " " + line; 713 sql = sql.trim(); 714 715 // SQL defines "--" as a comment to EOL 716 // and in Oracle it may contain a hint 717 // so we cannot just remove it, instead we must end it 718 if (line.indexOf("--") >= 0) 719 { 720 sql += "\n"; 721 } 722 723 if (delimiterType.equals(DelimiterType.NORMAL) 724 && sql.endsWith(delimiter) 725 || delimiterType.equals(DelimiterType.ROW) 726 && line.equals(delimiter)) 727 { 728 log("SQL: " + sql, Project.MSG_VERBOSE); 729 execSQL(sql.substring(0, sql.length() - delimiter.length()), 730 out); 731 sql = ""; 732 } 733 } 734 735 // Catch any statements not followed by ; 736 if (!sql.equals("")) 737 { 738 execSQL(sql, out); 739 } 740 } 741 catch (SQLException e) 742 { 743 throw e; 744 } 745 } 746 747 /*** 748 * Verify if connected to the correct RDBMS 749 * 750 * @param conn 751 */ 752 protected boolean isValidRdbms(Connection conn) 753 { 754 if (rdbms == null && version == null) 755 { 756 return true; 757 } 758 759 try 760 { 761 DatabaseMetaData dmd = conn.getMetaData(); 762 763 if (rdbms != null) 764 { 765 String theVendor = dmd.getDatabaseProductName().toLowerCase(); 766 767 log("RDBMS = " + theVendor, Project.MSG_VERBOSE); 768 if (theVendor == null || theVendor.indexOf(rdbms) < 0) 769 { 770 log("Not the required RDBMS: " 771 + rdbms, Project.MSG_VERBOSE); 772 return false; 773 } 774 } 775 776 if (version != null) 777 { 778 String theVersion = dmd.getDatabaseProductVersion() 779 .toLowerCase(); 780 781 log("Version = " + theVersion, Project.MSG_VERBOSE); 782 if (theVersion == null || !(theVersion.startsWith(version) 783 || theVersion.indexOf(" " + version) >= 0)) 784 { 785 log("Not the required version: \"" + version + "\"", 786 Project.MSG_VERBOSE); 787 return false; 788 } 789 } 790 } 791 catch (SQLException e) 792 { 793 // Could not get the required information 794 log("Failed to obtain required RDBMS information", Project.MSG_ERR); 795 return false; 796 } 797 798 return true; 799 } 800 801 /*** 802 * Exec the sql statement. 803 * 804 * @param sql 805 * @param out 806 * @throws SQLException 807 */ 808 protected void execSQL(String sql, PrintStream out) throws SQLException 809 { 810 // Check and ignore empty statements 811 if ("".equals(sql.trim())) 812 { 813 return; 814 } 815 816 try 817 { 818 totalSql++; 819 if (!statement.execute(sql)) 820 { 821 log(statement.getUpdateCount() + " rows affected", 822 Project.MSG_VERBOSE); 823 } 824 else 825 { 826 if (print) 827 { 828 printResults(out); 829 } 830 } 831 832 SQLWarning warning = conn.getWarnings(); 833 while (warning != null) 834 { 835 log(warning + " sql warning", Project.MSG_VERBOSE); 836 warning = warning.getNextWarning(); 837 } 838 conn.clearWarnings(); 839 goodSql++; 840 } 841 catch (SQLException e) 842 { 843 log("Failed to execute: " + sql, Project.MSG_ERR); 844 if (!onError.equals("continue")) 845 { 846 throw e; 847 } 848 log(e.toString(), Project.MSG_ERR); 849 } 850 } 851 852 /*** 853 * print any results in the statement. 854 * 855 * @param out 856 * @throws SQLException 857 */ 858 protected void printResults(PrintStream out) throws java.sql.SQLException 859 { 860 ResultSet rs = null; 861 do 862 { 863 rs = statement.getResultSet(); 864 if (rs != null) 865 { 866 log("Processing new result set.", Project.MSG_VERBOSE); 867 ResultSetMetaData md = rs.getMetaData(); 868 int columnCount = md.getColumnCount(); 869 StringBuffer line = new StringBuffer(); 870 if (showheaders) 871 { 872 for (int col = 1; col < columnCount; col++) 873 { 874 line.append(md.getColumnName(col)); 875 line.append(","); 876 } 877 line.append(md.getColumnName(columnCount)); 878 out.println(line); 879 line.setLength(0); 880 } 881 while (rs.next()) 882 { 883 boolean first = true; 884 for (int col = 1; col <= columnCount; col++) 885 { 886 String columnValue = rs.getString(col); 887 if (columnValue != null) 888 { 889 columnValue = columnValue.trim(); 890 } 891 892 if (first) 893 { 894 first = false; 895 } 896 else 897 { 898 line.append(","); 899 } 900 line.append(columnValue); 901 } 902 out.println(line); 903 line.setLength(0); 904 } 905 } 906 } 907 while (statement.getMoreResults()); 908 out.println(); 909 } 910 911 /*** 912 * Enumerated attribute with the values "continue", "stop" and "abort" 913 * for the onerror attribute. 914 */ 915 public static class OnError extends EnumeratedAttribute 916 { 917 public String[] getValues() 918 { 919 return new String[] {"continue", "stop", "abort"}; 920 } 921 } 922 923 /*** 924 * Contains the definition of a new transaction element. 925 * Transactions allow several files or blocks of statements 926 * to be executed using the same JDBC connection and commit 927 * operation in between. 928 */ 929 public class Transaction 930 { 931 private File tSrcFile = null; 932 private String tSqlCommand = ""; 933 934 public void setSrc(File src) 935 { 936 this.tSrcFile = src; 937 } 938 939 public void addText(String sql) 940 { 941 this.tSqlCommand += sql; 942 } 943 944 private void runTransaction(PrintStream out) 945 throws IOException, SQLException 946 { 947 if (tSqlCommand.length() != 0) 948 { 949 log("Executing commands", Project.MSG_INFO); 950 runStatements(new StringReader(tSqlCommand), out); 951 } 952 953 if (tSrcFile != null) 954 { 955 log("Executing file: " + tSrcFile.getAbsolutePath(), 956 Project.MSG_INFO); 957 Reader reader = (encoding == null) ? new FileReader(tSrcFile) 958 : new InputStreamReader(new FileInputStream(tSrcFile), 959 encoding); 960 runStatements(reader, out); 961 reader.close(); 962 } 963 } 964 } 965 }

This page was automatically generated by Maven