package detectabilityMethodChecks;

import java.sql.*;

/**
 * @author dag.wanvik@sun.com
 */
public class Main {
    
    Connection con = null;

    /** Creates a new instance of Main */
    public Main() {
    }

    private org.apache.derby.drda.NetworkServerControl netServer;
      
    private void startServer() {
        try {
            netServer = new org.apache.derby.drda.NetworkServerControl
                (java.net.InetAddress.getByName("localhost"), 1500);
            java.io.PrintWriter consoleWriter = new java.io.PrintWriter
                (System.out, true);
            netServer.start(consoleWriter);
            boolean knowIfServerUp = false; // do we know if server is
            // ready to accept connections  
            int numTimes = 5;

            // Test to see if server is ready for connections, for 15 seconds.
            while(!knowIfServerUp && (numTimes >0)) {
                try {
                    // testing for connection to see if the network server
                    // is up and running if server is not ready yet, this
                    // method will throw an exception 
                    numTimes--;
                    netServer.ping();
                    knowIfServerUp = true;
                }
                catch(Exception e) {
                    System.out.println("[NsSample] Unable to obtain a " + 
                                       "connection to network server, " + 
                                       "trying again after 3000 ms.");
                    Thread.currentThread().sleep(3000);
                }
            }
        } catch (Exception e) {
            System.out.println("Error starting server: " + e.toString());
        }
    }
    
    private void shutdownServer() {
        try {
            netServer.shutdown();
        } catch (Exception e) {
            System.out.println("Error shuting down: " + e.toString());
        }
    }

    private void dropTable() {
        try {
            Statement st = con.createStatement();
            st.execute("DROP TABLE mytab");
            st.close();
        } catch (SQLException sqlE) {
            // expected
        } catch (Exception e) {
            System.out.println("Error dropping table: " + e.toString());
        }
    }

    private void createTable() {
        try {
            Statement st = con.createStatement();
            st.execute("CREATE TABLE mytab (id int primary key, " + 
                       "name varchar(50))");
        } catch (SQLException sqlE) {
            System.out.println("Error creating table: " + sqlE.toString());
        } catch (Exception e) {
            System.out.println("Error creating table: " + e.toString());
        }
    }

    private void insertData() {
        try {
            int i;
            PreparedStatement ps = con.prepareStatement
                ("INSERT INTO mytab VALUES (?, ?)");
            for (i=0; i<10; i++) {
                ps.setInt(1, i);
                ps.setString(2, "Testing " + i);
                ps.executeUpdate();
            }

            ps.close();
        } catch (SQLException sqlE) {
            System.out.println("Error inserting data: " + sqlE.toString());
        }
    }

    private void dumpRows() {
        try {
            int i=0;
            Statement s = con.createStatement();

            ResultSet rs = s.executeQuery("SELECT * from mytab");
            
            while (rs.next()) {
                System.out.println("row " + i + ": " + rs.getInt(1) + " " + 
                                   rs.getString(2));
                i++;
            }

            s.close();
        } catch (SQLException sqlE) {
            System.out.println("Error dumping rows: " + sqlE.toString());
        }
    }
    
    private void doAfterLastThenTryDetectability() {
        Statement s = null; 
        ResultSet rs = null;

        try {
            s = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                                    ResultSet.CONCUR_UPDATABLE);
            rs = s.executeQuery("SELECT * from mytab");

            rs.last();
            rs.deleteRow();
            rs.afterLast();
            System.out.println("------ doAfterLastThenTryDetectability");

            try {
                boolean b = rs.rowDeleted();
                System.out.println("Bug reproduced: expected exception on " + 
                                   "rowDeleted: Got " + b);
            } catch (SQLException e) {
                System.out.println("Bug fixed for this case: " + 
                                   e.getSQLState() + ": " + e);
            }

        } catch (SQLException e) {
            System.out.println("Error in doAfterLastThenTryDetectability: " + e.getSQLState() +
                               ": " + e);
        } finally {
            if (rs != null) {
                try { rs.close(); } catch (Exception e) {};
            }
            if (s != null) {
                try { s.close(); } catch (Exception e) {};
            }
        }


    }

    private void doMoveToInsertRowThenTryDetectability() {
        Statement s = null; 
        ResultSet rs = null;

        try {
            s = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                                    ResultSet.CONCUR_UPDATABLE);
            rs = s.executeQuery("SELECT * from mytab");

            System.out.println("------ doMoveToInsertRowThenTryDetectability");
            rs.next();
            rs.moveToInsertRow();

            try {
                boolean b = rs.rowDeleted();
                System.out.println("Bug reproduced: expected exception on " + 
                                   "rowDeleted: Got " + b);
            } catch (SQLException e) {
                System.out.println("Bug fixed for this case: " + 
                                   e.getSQLState() + ": " + e);
            }

        } catch (SQLException e) {
            System.out.println("Error in doMoveToInsertRowThenTryDetectability: " + e.getSQLState() +
                               ": " + e);
        } finally {
            if (rs != null) {
                try { rs.close(); } catch (Exception e) {};
            }
            if (s != null) {
                try { s.close(); } catch (Exception e) {};
            }
        }


    }

    private void doBothDrivers(){
        Statement selectStatement = null;
        ResultSet rs = null;
        Statement st = null;

        String urls[] = {"jdbc:derby://localhost:1500/test1;create=true;"+
                         "territory=en_US",
                         "jdbc:derby:test1;create=true;territory=en_US"};
        String drivers[] = {"org.apache.derby.jdbc.ClientDriver",
                            "org.apache.derby.jdbc.EmbeddedDriver"};

        for (int dNo = 0; dNo < 2; dNo++) {
            try {
                Class.forName(drivers[dNo]);
                con = DriverManager.getConnection(urls[dNo]);
                
                System.out.println("* Testing with " + drivers[dNo] );

                dropTable();
                createTable();
                insertData();

                doAfterLastThenTryDetectability();
                doMoveToInsertRowThenTryDetectability();

                dumpRows();
                con.close();

            } catch (Exception e) {
                System.out.println(e.toString());
            }

        }

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Main m = new Main();
        m.startServer();
        m.doBothDrivers();
        m.shutdownServer();
    }
    
}

// Local Variables: ***
// indent-tabs-mode: nil ***
// fill-column: 79 ***
// End: ***
