import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

import org.postgresql.Driver;
import org.postgresql.ssl.ValidatingFactory;


/**
 * An example class which makes used of a custom keystore to validate the
 * authenticity of the server, and to assert the identity of the client.
 * <p>
 * Assuming your server's certificate has been signed by the CA whose 
 * key is located in rootca.crt, then you can create a key store which 
 * contains both the client key and the CA's certificate by running 
 * the following commands:
 * <code>
   keytool -genkey -alias testuser -keystore postgresql.jks
   keytool -certreq -alias testuser -file newreq.pem -keystore postgresql.jks
   keytool -import -trustcacerts -file rootca.crt -keystore postgresql.jks
   (your certificate request will need to be completed and returned to you before
    completing the next step)
   keytool -import -alias testuser -file newcert.pem -keystore postgresql.jks
  </code>
 * Note that user's of the OpenSSL "CA" script will be familiar with the file
 * names newreq.pem and newcert.pem. If you use that script, you'll need to 
 * edit the newcert.pem file so that all headers are removed, and only the 
 * CERTIFICATE block remains.
 * 
 * Then execute this class to see if it works. Note that if the root certificate
 * must be in your database diretory as root.crt in order to force client
 * authentication.
 */
public class ServerAndClientValidate {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		Properties props = new Properties();
		// these properties are most likely required, depending on your
		// database set up.
		props.setProperty("user","testuser");
		props.setProperty("password","PASSWORD");

		// Indicate that you want SSL.
		props.setProperty("ssl", "true");
		// Specify the Validating factory provided with the patch.
		props.setProperty("sslfactory", ValidatingFactory.class.getName());
	
		// The password to decrypt the keystore in question. If this is not
		// supplied, then an empty password will be used. I haven't figured out
		// how to create a keystore with no password, so this option is effectively
		// required.
		props.setProperty(ValidatingFactory.SSL_KEYSTORE_PASSWORD, "PASSWORD");

		// indicate that the trust store is the same as the client key store.
		props.setProperty(ValidatingFactory.SSL_KEYSTORE_IS_TRUSTSTORE, "");
		
		// Use the protocol of your choice.
		props.setProperty(ValidatingFactory.SSL_PROTOCOL, "TLS");
		
		// connect, query, go wild....
		Class c = Driver.class;
		String url = "jdbc:postgresql://host/testdb";
		Connection conn = DriverManager.getConnection(url, props);
		
		Statement st = conn.createStatement();
		ResultSet rs = st.executeQuery("SELECT version();");
		while (rs.next()) {
			System.out.println(rs.getString(1));
		}
		rs.close();
		st.close();
		conn.close();		
	}
}
