package org.realityforge.jeo.geolatte.jpa.eclipselink;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

final class DatabaseTestUtil
{
  private static final String URL_KEY = "javax.persistence.jdbc.url";
  private static final String DRIVER_KEY = "javax.persistence.jdbc.driver";
  private static final String USER_KEY = "javax.persistence.jdbc.user";
  private static final String PASSWORD_KEY = "javax.persistence.jdbc.password";

  private DatabaseTestUtil()
  {
  }

  static Properties initDatabaseProperties( final boolean control )
  {
    final String baseURL = System.getProperty( "test.db.base_url", "jdbc:postgresql://127.0.0.1:5432" );

    final Properties properties = new Properties();
    properties.put( DRIVER_KEY, "org.postgresql.Driver" );
    final String databaseUrl = baseURL + "/" + ( control ? "postgres" : "geolatte_test" );
    setProperty( properties, URL_KEY, "test.db.url", databaseUrl );
    setProperty( properties, USER_KEY, "test.db.user", "postgres" );
    setProperty( properties, PASSWORD_KEY, "test.db.password", null );
    properties.put( "eclipselink.session-event-listener", GeolatteExtension.class.getName() );
    return properties;
  }

  private static void setProperty( final Properties properties,
                                   final String key,
                                   final String systemPropertyKey,
                                   final String defaultValue )
  {
    final String value = System.getProperty( systemPropertyKey, defaultValue );
    if ( null != value )
    {
      properties.put( key, value );
    }
  }

  public static EntityManager createEntityManager( final String persistenceUnitName )
  {
    final Properties properties = initDatabaseProperties( false );
    final EntityManagerFactory factory = Persistence.createEntityManagerFactory( persistenceUnitName, properties );
    return factory.createEntityManager();
  }

  public static void setupDatabase()
    throws Exception
  {
    try
    {
      tearDownDatabase();
    }
    catch ( Exception e )
    {
      //Ignore
    }
    final Connection connection = initConnection( true );
    try
    {
      connection.createStatement().execute( "CREATE DATABASE geolatte_test" );
    }
    finally
    {
      disposeConnection( connection );
    }
    final Connection connection2 = initConnection( false );
    try
    {
      connection2.createStatement().execute( "CREATE EXTENSION postgis" );
    }
    finally
    {
      disposeConnection( connection2 );
    }
  }

  static void tearDownDatabase()
    throws Exception
  {
    final Connection connection = initConnection( true );
    try
    {
      connection.createStatement().execute( "SELECT pg_terminate_backend(pg_stat_activity.pid)\n" +
                                            "FROM pg_stat_activity\n" +
                                            "WHERE pg_stat_activity.datname = 'geolatte_test'" );
      connection.createStatement().execute( "DROP DATABASE geolatte_test" );
    }
    finally
    {
      disposeConnection( connection );
    }
  }
  private static void disposeConnection( final Connection connection )
  {
    if ( null != connection )
    {
      try
      {
        connection.close();
      }
      catch ( final Exception e )
      {
        throw new IllegalStateException( e.getMessage(), e );
      }
    }
  }

  private static Connection initConnection( final boolean control )
  {
    final Properties properties = initDatabaseProperties( control );
    try
    {
      Class.forName( properties.getProperty( DRIVER_KEY ) );
    }
    catch ( final Exception e )
    {
      throw new IllegalStateException( e.getMessage(), e );
    }
    try
    {
      return DriverManager.getConnection( properties.getProperty( URL_KEY ),
                                          properties.getProperty( USER_KEY ),
                                          properties.getProperty( PASSWORD_KEY ) );
    }
    catch ( final Exception e )
    {
      throw new IllegalStateException( e.getMessage(), e );
    }
  }
}

@@ -100,32 +100,89 @@
 .DriverManager;%0A
+import java.sql.SQLException;%0Aimport java.sql.Statement;%0A
 import java.util
@@ -2358,32 +2358,41 @@
  try%0A    %7B%0A     
+ execute(
  connection.crea
@@ -2390,35 +2390,9 @@
 tion
-.createStatement().execute(
+,
  %22CR
@@ -2563,32 +2563,41 @@
  try%0A    %7B%0A     
+ execute(
  connection2.cre
@@ -2596,35 +2596,9 @@
 ion2
-.createStatement().execute(
+,
  %22CR
@@ -2839,127 +2839,308 @@
     
-connection.createStatement().execute( %22SELECT pg_terminate_backend(pg_stat_activity.pid)%5Cn%22 +%0A           
+// Post 9.1 terminate option%0A      final int majorVersion = connection.getMetaData().getDatabaseMajorVersion();%0A      final int minorVersion = connection.getMetaData().getDatabaseMinorVersion();%0A      final int version = majorVersion * 100 + minorVersion;%0A      if ( version %3E= 902 )%0A
       
+%7B%0A
         
     
@@ -3139,81 +3139,207 @@
     
-                   %22FROM pg_stat_activity%5Cn%22 +
+execute( connection,%0A                 %22SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'geolatte_test'%22 );
 %0A      
+%7D%0A
       
+else%0A
       
+%7B%0A
         
     
@@ -3338,27 +3338,123 @@
     
-                  %22
+execute( connection,%0A                 %22SELECT pg_terminate_backend(pg_stat_activity.procpid) FROM pg_stat_activity 
 WHER
@@ -3512,45 +3512,36 @@
     
-connection.createStatement().execute(
+%7D%0A      execute( connection,
  %22DR
@@ -3643,16 +3643,244 @@
   %7D%0A  %7D%0A
+%0A  private static void execute( final Connection connection, final String sql )%0A    throws SQLException%0A  %7B%0A    final Statement statement = connection.createStatement();%0A    statement.execute( sql );%0A    statement.close();%0A  %7D%0A%0A
   privat

Support pre and post 9.2 versions of postgres