001: /*
002: * Copyright 2004 Clinton Begin
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package com.ibatis.common.jdbc;
017:
018: import com.ibatis.common.resources.Resources;
019:
020: import java.io.IOException;
021: import java.io.LineNumberReader;
022: import java.io.PrintWriter;
023: import java.io.Reader;
024: import java.sql.*;
025:
026: /**
027: * Tool to run database scripts
028: */
029: public class ScriptRunner {
030:
031: //private static final Log log = LogFactory.getLog(ScriptRunner.class);
032:
033: private Connection connection;
034: private String driver;
035: private String url;
036: private String username;
037: private String password;
038:
039: private boolean stopOnError;
040: private boolean autoCommit;
041:
042: private PrintWriter logWriter = new PrintWriter(System.out);
043: private PrintWriter errorLogWriter = new PrintWriter(System.err);
044:
045: /**
046: * Default constructor
047: */
048: public ScriptRunner(Connection connection, boolean autoCommit,
049: boolean stopOnError) {
050: this .connection = connection;
051: this .autoCommit = autoCommit;
052: this .stopOnError = stopOnError;
053: }
054:
055: public ScriptRunner(String driver, String url, String username,
056: String password, boolean autoCommit, boolean stopOnError) {
057: this .driver = driver;
058: this .url = url;
059: this .username = username;
060: this .password = password;
061: this .autoCommit = autoCommit;
062: this .stopOnError = stopOnError;
063: }
064:
065: /**
066: * Setter for logWriter property
067: *
068: * @param logWriter - the new value of the logWriter property
069: */
070: public void setLogWriter(PrintWriter logWriter) {
071: this .logWriter = logWriter;
072: }
073:
074: /**
075: * Setter for errorLogWriter property
076: *
077: * @param errorLogWriter - the new value of the errorLogWriter property
078: */
079: public void setErrorLogWriter(PrintWriter errorLogWriter) {
080: this .errorLogWriter = errorLogWriter;
081: }
082:
083: /**
084: * Runs an SQL script (read in using the Reader parameter)
085: *
086: * @param reader - the source of the script
087: */
088: public void runScript(Reader reader) throws IOException,
089: SQLException {
090: try {
091: if (connection == null) {
092: DriverManager.registerDriver((Driver) Resources
093: .classForName(driver).newInstance());
094: Connection conn = DriverManager.getConnection(url,
095: username, password);
096: try {
097: if (conn.getAutoCommit() != autoCommit) {
098: conn.setAutoCommit(autoCommit);
099: }
100: runScript(conn, reader);
101: } finally {
102: conn.close();
103: }
104: } else {
105: boolean originalAutoCommit = connection.getAutoCommit();
106: try {
107: if (originalAutoCommit != this .autoCommit) {
108: connection.setAutoCommit(this .autoCommit);
109: }
110: runScript(connection, reader);
111: } finally {
112: connection.setAutoCommit(originalAutoCommit);
113: }
114: }
115: } catch (IOException e) {
116: throw e;
117: } catch (SQLException e) {
118: throw e;
119: } catch (Exception e) {
120: throw new RuntimeException("Error running script. Cause: "
121: + e, e);
122: }
123: }
124:
125: /**
126: * Runs an SQL script (read in using the Reader parameter) using the connection passed in
127: *
128: * @param conn - the connection to use for the script
129: * @param reader - the source of the script
130: * @throws SQLException if any SQL errors occur
131: * @throws IOException if there is an error reading from the Reader
132: */
133: private void runScript(Connection conn, Reader reader)
134: throws IOException, SQLException {
135: StringBuffer command = null;
136: try {
137: LineNumberReader lineReader = new LineNumberReader(reader);
138: String line = null;
139: while ((line = lineReader.readLine()) != null) {
140: if (command == null) {
141: command = new StringBuffer();
142: }
143: String trimmedLine = line.trim();
144: if (trimmedLine.startsWith("--")) {
145: println(trimmedLine);
146: } else if (trimmedLine.length() < 1
147: || trimmedLine.startsWith("//")) {
148: //Do nothing
149: } else if (trimmedLine.length() < 1
150: || trimmedLine.startsWith("--")) {
151: //Do nothing
152: } else if (trimmedLine.endsWith(";")) {
153: command.append(line.substring(0, line
154: .lastIndexOf(";")));
155: command.append(" ");
156: Statement statement = conn.createStatement();
157:
158: println(command);
159:
160: boolean hasResults = false;
161: if (stopOnError) {
162: hasResults = statement.execute(command
163: .toString());
164: } else {
165: try {
166: statement.execute(command.toString());
167: } catch (SQLException e) {
168: e.fillInStackTrace();
169: printlnError("Error executing: " + command);
170: printlnError(e);
171: }
172: }
173:
174: if (autoCommit && !conn.getAutoCommit()) {
175: conn.commit();
176: }
177:
178: ResultSet rs = statement.getResultSet();
179: if (hasResults && rs != null) {
180: ResultSetMetaData md = rs.getMetaData();
181: int cols = md.getColumnCount();
182: for (int i = 0; i < cols; i++) {
183: String name = md.getColumnName(i);
184: print(name + "\t");
185: }
186: println("");
187: while (rs.next()) {
188: for (int i = 0; i < cols; i++) {
189: String value = rs.getString(i);
190: print(value + "\t");
191: }
192: println("");
193: }
194: }
195:
196: command = null;
197: try {
198: statement.close();
199: } catch (Exception e) {
200: // Ignore to workaround a bug in Jakarta DBCP
201: }
202: Thread.yield();
203: } else {
204: command.append(line);
205: command.append(" ");
206: }
207: }
208: if (!autoCommit) {
209: conn.commit();
210: }
211: } catch (SQLException e) {
212: e.fillInStackTrace();
213: printlnError("Error executing: " + command);
214: printlnError(e);
215: throw e;
216: } catch (IOException e) {
217: e.fillInStackTrace();
218: printlnError("Error executing: " + command);
219: printlnError(e);
220: throw e;
221: } finally {
222: conn.rollback();
223: flush();
224: }
225: }
226:
227: private void print(Object o) {
228: if (logWriter != null) {
229: System.out.print(o);
230: }
231: }
232:
233: private void println(Object o) {
234: if (logWriter != null) {
235: logWriter.println(o);
236: }
237: }
238:
239: private void printlnError(Object o) {
240: if (errorLogWriter != null) {
241: errorLogWriter.println(o);
242: }
243: }
244:
245: private void flush() {
246: if (logWriter != null) {
247: logWriter.flush();
248: }
249: if (errorLogWriter != null) {
250: errorLogWriter.flush();
251: }
252: }
253:
254: }
|