/*
 * JDBCDAOFactory.java
 *
 * Created on 10 aprile 2004, 10.32
 */

import java.util.Properties;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import java.sql.SQLException;

/**
 *
 * JDBCDAOFactory è la classe principale del DAO per JDBC.
 *
 * Il suo funzionamento è assicurato dalla lettura di alcune
 * proprietà dal file chiamato "my.properties" che si trova nella
 * directory corrente, cioè normalmente la $HOME dell'utente.
 *
 * In questo momento gestisce i driver JDBC di oracle, postgresql e mysql,
 * ma dovrebbe essere cambiato per essere completamente generico.
 *
 * Nota: il driver JDBC richiesto deve aderire allo standard 3.0
 *       per permettere una gestione corretta sia dei pool di connessioni
 *       sia dei BLOB (Binary Large Object).
 *
 * @author  giuseppe
 */
public class JDBCDAOFactory 
{
    final static String propertyFile = "my.properties";
    final static String dataSourceClassName = "db.dataSourceClassName";
    final static String databaseName = "db.databasename";
    final static String serverName = "db.servername";
    final static String serverPortNumber = "db.serverportnumber";
    
    private ConnectionPoolDataSource connectionPoolDataSource;

    /** Creates a new instance of JDBCDAOFactory 
     * La classe oracle dovrebbe essere oracle.jdbc.pool.OracleConnectionPoolDataSource
     * quella postgresql dovrebbe essere org.postgresql.jdbc3.Jdbc3PoolingDataSource
     * quella mysql dovrebbe essere gwe.sql.gweMysqlConnectionPoolDataSource
     *
     * nota: il costruttore per oracle *richiede* che venga definito il DriverType.
     */
     public JDBCDAOFactory(String login, String password)
                throws SQLException, FileNotFoundException, IOException,
                        ClassNotFoundException, InstantiationException, IllegalAccessException {

        Properties prop = new Properties();
        String dataSourceName;
        
        prop.load(new FileInputStream(propertyFile));
        dataSourceName = prop.getProperty(dataSourceClassName);
        connectionPoolDataSource = (ConnectionPoolDataSource)(Class.forName(dataSourceName).newInstance());

        try {
                String nomeClasse = prop.getProperty(dataSourceClassName);
                Class classe = Class.forName(nomeClasse);
                Object conDS = classe.newInstance();
                java.lang.reflect.Method metodo;
                Class argomenti[] = new Class[1];
                String args[] = new String[1];

                /*
                 * Invoco il metodo setServerName()
                 */

                argomenti[0] = String.class;
                metodo = classe.getMethod("setServerName", argomenti);
                args[0] = prop.getProperty(serverName, "localhost");
                metodo.invoke(conDS, args);

                /*
                 * Invoco il metodo setPortNumber()
                 */

                if (prop.getProperty(serverPortNumber) != null) {
                    Integer iargs[] = new Integer[1];
                    iargs[0] = new Integer(prop.getProperty(serverPortNumber));

                    try {
                        argomenti[0] = Class.forName("java.lang.Integer");
                        metodo = classe.getMethod("setPortNumber", argomenti);
                        metodo.invoke(conDS, iargs);
                    }
                    catch (Exception e) { /* funziona solo con mySQL e fallisce con gli altri */ }

                    try {
                        argomenti[0] = int.class;
                        metodo = classe.getMethod("setPortNumber", argomenti);
                        metodo.invoke(conDS, iargs);
                    }
                    catch (Exception e) { /* funziona con tutti salvo mySQL */ }
                }

                /*
                 * Invoco il metodo setDatabaseName()
                 */
                argomenti[0] = String.class;
                metodo = classe.getMethod("setDatabaseName", argomenti);
                args[0] = prop.getProperty(databaseName);
                metodo.invoke(conDS, args);

                /*
                 * Invoco il metodo setDriverType() che esiste (e va chiamato)
                 * solo per Oracle.
                 */

                try {
                    argomenti[0] = String.class;
                    metodo = classe.getMethod("setDriverType", argomenti);
                    args[0] = "thin";
                    metodo.invoke(conDS, args);
                }
                catch (Exception e) { /* funziona solo con oracle e fallisce con gli altri */ }

                /*
                 * Invoco il metodo setUser()
                 */
                argomenti[0] = String.class;
                metodo = classe.getMethod("setUser", argomenti);
                args[0] = login;
                metodo.invoke(conDS, args);
                
                /*
                 * Invoco il metodo setPassword()
                 */
                argomenti[0] = String.class;
                metodo = classe.getMethod("setPassword", argomenti);
                args[0] = password;
                metodo.invoke(conDS, args);

                /*
                 * Verifico quello che ho fatto invocando il metodo setURL()
                 */
                try {
                    metodo = classe.getMethod("getURL", null);
                    args[0] = (String)(metodo.invoke(conDS, null));
                }
                catch (Exception e) {
                    try {
                        metodo = classe.getMethod("getUrl", null);
                        args[0] = (String)(metodo.invoke(conDS, null));
                    }
                    catch (Exception ee) {
                        args[0] = null;
                    }
                }
                if (args[0] != null)
                    System.err.println("getUrl() = " + args[0]);
            }
            catch (Exception e) {
                throw (new SQLException("JDBC source not permitted. " + e.toString()));
            }
//        }
    }
    
}
