import org.apache.derby.drda.NetworkServerControl;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.PrintWriter;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

/**
 * Created by IntelliJ IDEA.
 * User: Pavel Bortnovskiy (pbortnovskiy@JEFCO)
 * Created: on Oct 22, 2010 at 11:20:42 AM
 */
final public class DerbyTest {
    private static final Logger logger = Logger.getLogger(DerbyTest.class);

    @BeforeClass
    public static void setUpClass() throws Exception {
        BasicConfigurator.configure();
    }

    private boolean checkTable(final Connection connection, final String tableName) throws SQLException {
        final DatabaseMetaData databaseMetaData = connection.getMetaData();
        final ResultSet resultSet = databaseMetaData.getTables(null, null,
                tableName.toUpperCase(), new String[]{"TABLE"});
        boolean found = false;
        while (!found && resultSet.next()) {
            if (resultSet.getString("TABLE_NAME").equalsIgnoreCase(tableName)) {
                found = true;
            }
        }
        if (found) {
            final Statement statement = connection.createStatement();
            final ResultSet rs = statement.executeQuery("SELECT * FROM " + tableName);
            while (rs.next()) {
                logger.info(rs.getString("Name") + ", " + rs.getString("Value"));
            }
        }
        return found;
    }

    private boolean createTable(final Connection connection, final String tableName) throws SQLException {
        final Statement statement = connection.createStatement();
        try {
            final String createTableStatement = "CREATE TABLE " + tableName +
                    " (Name VARCHAR(256) NOT NULL, Value VARCHAR(256), PRIMARY KEY(Name))";
            statement.executeUpdate(createTableStatement);
            final String insertStatement = "INSERT INTO " + tableName + "(Name, Value) VALUES ('One', 'Two')";
            statement.executeUpdate(insertStatement);
            return true;
        } catch (SQLException e) {
            logger.error(e);
            return false;
        }
    }

    private void testDerby(final int port) throws Exception {
        Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();

        final Connection connection = DriverManager.getConnection("jdbc:derby:memory:test;create=true");

        final NetworkServerControl control = new NetworkServerControl(InetAddress.getLocalHost(), port);

        control.start(new PrintWriter(System.out));

        final String tableName = "source_table";

        assertFalse("Table " + tableName + " must not exist", checkTable(connection, tableName));
        assertTrue("Unable to create " + tableName, createTable(connection, tableName));
        assertTrue("Table " + tableName + " must exist", checkTable(connection, tableName));

        control.shutdown();

        try {
            DriverManager.getConnection("jdbc:derby:;shutdown=true");
        } catch (SQLException e) {
            assertTrue("Invalid Shutdown Codes", e.getErrorCode() == 50000 && "XJ015".equals(e.getSQLState()));
        }
    }

    @Test
    public void testFirstDerby() throws Exception {
        testDerby(3344);
    }

    @Test
    public void testSecondDerby() throws Exception {
        testDerby(3344);
    }
}
