package journal.action; import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger; import journal.action.sql.SQLAdapter; import journal.reader.DataJournalEntry; import journal.reader.Options; import journal.reader.TransactionJournalEntry; public class SQLUpdater extends BaseAction { protected Connection cx; protected SQLAdapter sf; protected String classpath; protected String classname; protected String connectionString; protected void handleSQLException(SQLException ex) throws Exception { StringBuffer err = new StringBuffer(); err.append( "SQLException: " + ex.getMessage() ); err.append( " SQLState: " + ex.getSQLState() ); err.append( " VendorError: " + ex.getErrorCode() ); Exception newEx = new Exception(err.toString()); newEx.setStackTrace(ex.getStackTrace()); throw newEx; } final static class DriverProxy implements java.sql.Driver { private final java.sql.Driver target; DriverProxy(java.sql.Driver target) { if (target == null) { throw new NullPointerException(); } this.target = target; } public java.sql.Driver getTarget() { return target; } public boolean acceptsURL(String url) throws SQLException { return target.acceptsURL(url); } public java.sql.Connection connect( String url, java.util.Properties info ) throws SQLException { return target.connect(url, info); } public int getMajorVersion() { return target.getMajorVersion(); } public int getMinorVersion() { return target.getMinorVersion(); } public java.sql.DriverPropertyInfo[] getPropertyInfo( String url, java.util.Properties info ) throws SQLException { return target.getPropertyInfo(url, info); } public boolean jdbcCompliant() { return target.jdbcCompliant(); } @Override public String toString() { return "Proxy: "+target; } @Override public int hashCode() { return target.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof DriverProxy)) { return false; } DriverProxy other = (DriverProxy)obj; return this.target.equals(other.target); } // for Java 1.7, no @Override to be compatible with 1.6 public Logger getParentLogger() throws SQLFeatureNotSupportedException { // TODO Auto-generated method stub return null; } } @Override public void setDefaultOptions(Options options) { options.setOptionName(this.getClass().getName(), "classpath", "", new Options.OptionSetter() { @Override public void set(String key, String value) { classpath=value; } }); options.setOptionName(this.getClass().getName(), "classname", "", new Options.OptionSetter() { @Override public void set(String key, String value) { classname=value; } }); options.setOptionName(this.getClass().getName(), "connectionString", "", new Options.OptionSetter() { @Override public void set(String key, String value) { connectionString=value; } }); } @Override public void start() throws Exception { super.start(); if (classpath == "" || classname == "" || connectionString == "") { String message = "No SQL parameters defined CP=" + classpath + " CN=" + classname + " CON=" + connectionString; throw new Exception(message); } File jarFile = new File(classpath); URL url = jarFile.toURI().toURL(); ClassLoader ld = URLClassLoader.newInstance(new URL[] { url }, getClass().getClassLoader()); Driver driver = (Driver) Class.forName(classname, true, ld).newInstance(); DriverManager.registerDriver(new DriverProxy(driver)); try { cx = DriverManager.getConnection(connectionString); cx.setAutoCommit(false); sf = new SQLAdapter(cx, options); } catch (SQLException ex) { handleSQLException(ex); } System.out.println("Connected to " + cx); } @Override public void finish() throws Exception { try { cx.close(); } catch (SQLException ex) { handleSQLException(ex); } System.out.println("Disconnected from SQL Database."); } @Override public void commitMarker(TransactionJournalEntry entry) throws Exception { try { cx.commit(); } catch (SQLException ex) { handleSQLException(ex); } } @Override public void flushMarker(TransactionJournalEntry entry) { // flush is ignored } @Override public void putValue(DataJournalEntry dataEntry) throws Exception { try { sf.putValue(dataEntry); } catch (SQLException ex) { handleSQLException(ex); } } @Override public void replaceValue(DataJournalEntry dataEntry) throws Exception { try { sf.replaceValue(dataEntry); } catch (SQLException ex) { handleSQLException(ex); } } @Override public void deleteValue(DataJournalEntry dataEntry) throws Exception { try { sf.deleteValue(dataEntry); } catch (SQLException ex) { handleSQLException(ex); } } @Override public void verifyValue(DataJournalEntry dataEntry) throws Exception { try { sf.verifyValue(dataEntry); } catch (SQLException ex) { handleSQLException(ex); } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 24773 | Norman Morse |
Moving journalReader from sven's private branch to perforce_software. This is because journalReader is used in the perfsplit test harness, and should be updated over time. Merging //guest/sven_erik_knop/java/JournalReader/... to //guest/perforce_software/journalReader/... |
||
//guest/sven_erik_knop/java/JournalReader/src/journal/action/SQLUpdater.java | |||||
#5 | 8296 | Sven Erik Knop |
Clean-up: instead of casting in every action, cast only once in the dispatcher. Should make code saner and safer. No functional change. |
||
#4 | 8203 | Sven Erik Knop | Let's try it again with java 1.6 | ||
#3 | 8201 | Sven Erik Knop |
CheckCase printed wrong count for conflicts. SQlUpdater had missing method for Java 1.7 |
||
#2 | 8023 | Sven Erik Knop |
Complete rewrite of the configuration file, now based on an ini-file format. The ini file has a general [reader] section for settings like verbose, outputFile, case-sensitivity and so on. It also allows to set up a range of Actions and Filters. The section name here is the fully classified class name, followed by settings for the particular actions. An example will make this clearer: ================================================================ [reader] verbose=true [journal.action.UserRenamer] fileName=user.txt patch=True outputFile=user.out [journal.action.ClientRenamer] fileName=client.txt outputFile=client.out patch=true ================================================================ I will provide more example set-ups in the near future. Filters are classes implementing journal.action.Filter (soon to be journal.filter.Filter) which can be chained together and are all executed before the actions. Actions are applied in order that they are given in the config file. |
||
#1 | 7527 | Sven Erik Knop |
JournalReader, now in its proper place. Documentation to follow. |