Quadcap Bug Database

com/quadcap/app/bugdb/Loader.java

Go to the documentation of this file.
00001 package com.quadcap.app.bugdb; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.BufferedInputStream; 00042 import java.io.File; 00043 import java.io.FileInputStream; 00044 import java.io.IOException; 00045 import java.io.InputStream; 00046 import java.io.PrintWriter; 00047 00048 import java.sql.Connection; 00049 import java.sql.DriverManager; 00050 import java.sql.ResultSet; 00051 import java.sql.ResultSetMetaData; 00052 import java.sql.SQLException; 00053 import java.sql.Statement; 00054 00055 /** 00056 * A simple SQL loader utility. 00057 * 00058 * @author Stan Bailes 00059 */ 00060 public class Loader { 00061 Connection conn; 00062 StringBuffer buffer = new StringBuffer(); 00063 PrintWriter writer = null; 00064 00065 /** 00066 * Construct a new loader. It needs a connection in order to do 00067 * anything useful. 00068 */ 00069 public Loader() { 00070 } 00071 00072 /** 00073 * Construct a new loader bound to the specified connection. 00074 * 00075 * @param conn the connection to use. 00076 */ 00077 public Loader(Connection conn) { 00078 this.conn = conn; 00079 } 00080 00081 /** 00082 * Set the loader's connection 00083 * 00084 * @param conn the connection to use. 00085 */ 00086 public void setConnection(Connection conn) { 00087 this.conn = conn; 00088 } 00089 00090 /** 00091 * Get the loaders's connection 00092 * 00093 * @return the loader's current connection 00094 */ 00095 public Connection getConnection() { 00096 return this.conn; 00097 } 00098 00099 /** 00100 * Get the PrintWriter used to display the results of select statements. 00101 * 00102 * @return the current writer 00103 */ 00104 public PrintWriter getWriter() { 00105 return writer; 00106 } 00107 00108 /** 00109 * Set the PrintWriter used to display the results of select statements. 00110 * 00111 * @param writer the new writer 00112 */ 00113 public void setWriter(PrintWriter writer) { 00114 this.writer = writer; 00115 } 00116 00117 /** 00118 * Print (if a writer is set) the specified string 00119 * 00120 * @param s the string 00121 */ 00122 final void print(String s) { 00123 if (writer != null) writer.print(s); 00124 } 00125 00126 /** 00127 * Print (if a writer is set) the specified string, 00128 * with a trailing newline. 00129 * 00130 * @param s the string 00131 */ 00132 final void println(String s) { 00133 if (writer != null) writer.println(s); 00134 } 00135 00136 /** 00137 * Print (if a writer is set) the stack trace for the specified throwable. 00138 * 00139 * @param t the throwable 00140 */ 00141 final void print(Throwable t) { 00142 if (writer != null) t.printStackTrace(writer); 00143 if (t instanceof SQLException) { 00144 SQLException e = ((SQLException)t).getNextException(); 00145 if (e != null) { 00146 print(e); 00147 } 00148 } 00149 } 00150 00151 /** 00152 * Return a string left-justified in a field 'wid' characters wide. 00153 * 00154 * @param wid the field width 00155 * @param s the input string 00156 * @return the padded string 00157 */ 00158 final static String pad(int wid, String s) { 00159 StringBuffer sb = new StringBuffer(s); 00160 while (sb.length() < wid) sb.append(' '); 00161 return sb.toString(); 00162 } 00163 00164 /** 00165 * Display a result set (to the current writer) 00166 * 00167 * @param rs the result set 00168 * @exception SQLException may be thrown 00169 */ 00170 final void showResultSet(ResultSet rs) throws SQLException { 00171 ResultSetMetaData rmeta = rs.getMetaData(); 00172 String delim = ""; 00173 for (int i = 1; i <= rmeta.getColumnCount(); i++) { 00174 int wid = rmeta.getColumnDisplaySize(i); 00175 if (wid > 32) wid = 32; 00176 print(delim); 00177 delim = " "; 00178 print(pad(wid, rmeta.getColumnName(i))); 00179 } 00180 println(""); 00181 while (rs.next()) { 00182 delim = ""; 00183 for (int i = 1; i <= rmeta.getColumnCount(); i++) { 00184 int wid = rmeta.getColumnDisplaySize(i); 00185 if (wid > 32) wid = 32; 00186 print(delim); 00187 delim = " "; 00188 Object obj = rs.getObject(i); 00189 if (obj == null) obj = "<null>"; 00190 if (obj instanceof byte[]) { 00191 obj = hexBytes((byte[])obj); 00192 } 00193 print(pad(wid, obj.toString())); 00194 } 00195 println(""); 00196 } 00197 } 00198 00199 /** 00200 * Return the next SQL command from the input stream. 00201 * 00202 * @param is the input stream 00203 * @return the SQL statement 00204 * @exception IOException may be thrown 00205 */ 00206 static String getLine(InputStream is) throws IOException { 00207 StringBuffer sb = new StringBuffer(); 00208 int ch; 00209 int state = 0; 00210 while ((ch = is.read()) > 0) { 00211 char c = (char)ch; 00212 switch (state) { 00213 case 0: 00214 if (c == '-') { 00215 state = 1; 00216 } else if (c == ';') { 00217 if (sb.length() > 0) { 00218 return sb.toString(); 00219 } 00220 } else if (Character.isWhitespace(c) && sb.length() == 0) { 00221 } else { 00222 sb.append(c); 00223 } 00224 break; 00225 case 1: 00226 if (c == '-') { 00227 state = 2; 00228 } else { 00229 sb.append('-'); 00230 sb.append(c); 00231 state = 0; 00232 } 00233 break; 00234 case 2: 00235 if (c == '\r') state = 3; 00236 if (c == '\n') state = 0; 00237 break; 00238 case 3: 00239 if (c == '\n') state = 0; 00240 break; 00241 } 00242 } 00243 return null; 00244 } 00245 00246 /** 00247 * Execute the specified SQL command 00248 * 00249 * @param sql the SQL statement to execute 00250 */ 00251 final void execute(String sql) { 00252 try { 00253 Statement stmt = conn.createStatement(); 00254 try { 00255 if (sql.equals("BEGINTRANSACTION")) { 00256 conn.setAutoCommit(false); 00257 } else if (sql.equals("ENDTRANSACTION") || 00258 sql.equals("COMMIT")) { 00259 conn.commit(); 00260 conn.setAutoCommit(true); 00261 } else if (sql.equals("ROLLBACK")) { 00262 conn.rollback(); 00263 conn.setAutoCommit(true); 00264 } else { 00265 if (stmt.execute(sql)) { 00266 ResultSet rs = stmt.getResultSet(); 00267 try { 00268 showResultSet(rs); 00269 } finally { 00270 rs.close(); 00271 } 00272 } 00273 } 00274 } catch (Throwable t) { 00275 print(t); 00276 } finally { 00277 stmt.close(); 00278 } 00279 } catch (Throwable t) { 00280 print(t); 00281 } 00282 } 00283 00284 /** 00285 * The main point of this class, which is to execute all the SQL commands 00286 * found in the specified file. 00287 * 00288 * @param filename the name of the file 00289 */ 00290 public void loadFile(String filename) throws IOException { 00291 FileInputStream fis = new FileInputStream(filename); 00292 loadStream(fis); 00293 } 00294 00295 /** 00296 * Execute the SQL script contained in the specified input stream 00297 * 00298 * @param is the input stream 00299 */ 00300 public void loadStream(InputStream is) { 00301 try { 00302 Statement stmt = conn.createStatement(); 00303 BufferedInputStream bis = new BufferedInputStream(is, 1024); 00304 String sql = null; 00305 while ((sql = getLine(bis)) != null) { 00306 try { 00307 if (sql.equals("BEGINTRANSACTION")) { 00308 conn.setAutoCommit(false); 00309 } else if (sql.equals("ENDTRANSACTION") || 00310 sql.equals("COMMIT")) { 00311 conn.commit(); 00312 conn.setAutoCommit(true); 00313 } else if (sql.equals("ROLLBACK")) { 00314 conn.rollback(); 00315 conn.setAutoCommit(true); 00316 } else { 00317 if (stmt.execute(sql)) { 00318 ResultSet rs = stmt.getResultSet(); 00319 showResultSet(rs); 00320 } 00321 } 00322 } catch (Throwable t) { 00323 print(t); 00324 } 00325 } 00326 } catch (Throwable t) { 00327 print(t); 00328 } finally { 00329 try { 00330 is.close(); 00331 } catch (Exception e) {} 00332 } 00333 } 00334 00335 static char[] hexMap = {'0', '1', '2', '3', '4', '5', '6', '7', 00336 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 00337 00338 /** 00339 * Return a string containing the hexadecimal representation of the 00340 * specified byte array 00341 * 00342 * @param buf the byte array 00343 * @return the ASCII hex representation of the byte array. 00344 */ 00345 public static String hexBytes(byte[] buf) { 00346 if (buf == null) return "<null>"; 00347 return hexBytes(buf, 0, buf.length); 00348 } 00349 00350 /** 00351 * Return a string containing the hexadecimal representation of 00352 * a portion of the specified byte array 00353 * 00354 * @param buf the byte array 00355 * @param off the position of the first byte to convert 00356 * @param len the number of bytes to convert 00357 * @return the ASCII hex representation of the bytes 00358 */ 00359 public static String hexBytes(byte[] buf, int off, int len) { 00360 if (buf == null) return "<null>"; 00361 StringBuffer sb = new StringBuffer(); 00362 for (int i = off; i < off + len; i++) { 00363 byte b = buf[i]; 00364 sb.append(hexMap[(b >> 4) & 0xf]); 00365 sb.append(hexMap[b & 0xf]); 00366 } 00367 return sb.toString(); 00368 } 00369 }