/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 Copyright (C) Picosoft s.r.l. 1995-2002

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
package IT.picosoft.jdbc;

// import java.security.AccessController;
import java.sql.*;
import java.util.*;
// import sun.security.action.GetPropertyAction;

public class PicoDriver implements Driver
{
    protected static PicoDbApi odbcApi;
    protected static int hEnv;
    protected static Hashtable connectionList;

    static {
        if (DriverManager.getLogWriter() != null)
           DriverManager.println("picoDB driver class loaded");
        PicoDriver drv = new PicoDriver();
        try {
            DriverManager.registerDriver(drv);
        } catch(SQLException ex) {
            if(DriverManager.getLogWriter() != null)
                DriverManager.println("Unable to register driver:" + ex);
        }
    }

    public PicoDriver() {
        odbcApi = null;
        hEnv = 0;
        connectionList = new Hashtable();
    }

    public void closeConnection (OdbcConnection odbcCon) throws SQLException {
      odbcCon.close();
      Object debug = connectionList.remove(odbcCon);
      if (connectionList.size() == 0 && hEnv != 0) {
         odbcApi.SQLFreeEnv(hEnv);
         hEnv = 0;
      }
   }

   public synchronized Connection connect(String url, Properties info)
                                          throws SQLException {
      if (DriverManager.getLogWriter() != null)
         DriverManager.println("*PicoDriver.connect (" + url + ") nConn=" +
                               connectionList.size());
      if (!acceptsURL(url))
         return null;
      if(!initialize()) {
         return null;
      } else {
         PicoConnection conn = new PicoConnection(hEnv, this);
         conn.initialize(getSubName(url),info,DriverManager.getLoginTimeout());
         conn.setURL(url);
         connectionList.put(conn.getHDBC(), new Integer(hEnv));
         return conn;
      }
   }

   public Hashtable getAttributeProperties(String s) {
      int i = 0;
      boolean flag = false;
      int j1 = 0;
      Hashtable hashtable = new Hashtable();
      int j;
      for (int k1 = s.length(); i < k1; i = j + 1) {
         boolean flag1 = true;
         String s2 = null;
         String s3 = null;
         String as[] = null;
         String s4 = null;
         j = s.indexOf(";", i);
         if (j < 0)
            j = k1 + 1;
         String s1 = s.substring(i, j);
         int k = 0;
         int l = s1.indexOf(":", 0);
         int i1 = s1.indexOf("=", 0);
         if (s1.startsWith("*")) {
            flag1 = false;
            k++;
         }
         if (l > 0)
            s2 = s1.substring(k, l);
         if (l > 0 && i1 > 0)
            s3 = s1.substring(l + 1, i1);
         if (i1 > 0) {
            s4 = s1.substring(i1 + 1);
            if (s4.equals("?"))
               s4 = null;
         }
         if (s4 != null && s4.startsWith("{")) {
            as = listToArray(s4);
            s4 = null;
         }
         DriverPropertyInfo driverpropertyinfo = new DriverPropertyInfo(s2, s4);
         driverpropertyinfo.description = s3;
         driverpropertyinfo.required = flag1;
         driverpropertyinfo.choices = as;
         hashtable.put(new Integer(j1), driverpropertyinfo);
         j1++;
      }

      return hashtable;
   }

   public int getMajorVersion() {
      return 1;
   }

   public int getMinorVersion() {
      return 2;
   }

   public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
                   throws SQLException {
      if (DriverManager.getLogWriter() != null)
         DriverManager.println("*PicoDriver.getPropertyInfo (" + url + ")");
      if(!acceptsURL(url))
         return null;
      if(!initialize())
         return null;
      return new DriverPropertyInfo[0];
   }

   public static String getProtocol(String s) {
      String s1 = "";
      int i = s.indexOf(':');
      if (i >= 0)
         s1 = s.substring(0, i);
      return s1;
   }

   public static String getSubName(String s) {
      String s1 = "";
      int i = s.indexOf(':');
      if (i >= 0) {
         int j = s.indexOf(':', i + 1);
         if (j >= 0)
            s1 = s.substring(j + 1);
      }
      return s1;
   }

   public static String getSubProtocol(String s) {
      String s1 = "";
      int i = s.indexOf(':');
      if (i >= 0) {
         int j = s.indexOf(':', i + 1);
         if (j >= 0)
            s1 = s.substring(i + 1, j);
       }
       return s1;
   }

   private boolean initialize() throws SQLException {
      boolean Return = true;
      if (odbcApi == null)
         try {
            odbcApi = new PicoDbApi ();
         } catch(Exception ex) {
            if (DriverManager.getLogWriter() != null)
               DriverManager.println("Unable to load PicoDbApi library:" + ex);
            Return = false;
         }
      if (hEnv == 0)
         try {
            hEnv = odbcApi.SQLAllocEnv();
         } catch(Exception ex) {
            if (DriverManager.getLogWriter() != null)
               DriverManager.println("Unable to allocate environment:" + ex);
            Return = false;
         }
      return Return;
   }

   public boolean jdbcCompliant() {
      return true;
   }

   public boolean acceptsURL(String url) {
      if (DriverManager.getLogWriter() != null) {
         DriverManager.println("acc. url=" + url);
         DriverManager.println("acc. prt=" + getProtocol(url));
         DriverManager.println("acc. sub=" + getSubProtocol(url));
      }
      return  getProtocol(url).equalsIgnoreCase("jdbc") &&
              getSubProtocol(url).equalsIgnoreCase("picoDB");
   }

   protected static String[] listToArray(String s) {
      String as[] = null;
      Hashtable hashtable = new Hashtable();
      int i = 0;
      int j = 1;
      boolean flag = true;
      int i1 = s.length();
      if (!s.startsWith("{"))
         return null;
      if (!s.endsWith("}"))
         return null;
      int l;
      for (; j < i1; j = l + 1) {
         l = s.indexOf(",", j);
         if (l < 0)
            l = i1 - 1;
         String s1 = s.substring(j, l);
         hashtable.put(new Integer(i), s1);
         i++;
      }

      as = new String[i];
      for (int k = 0; k < i; k++) {
         String s2 = (String)hashtable.get(new Integer(k));
         as[k] = s2;
      }

      return as;
   }

   protected static String makeConnectionString(Properties properties) {
      String s = "";
      for (Enumeration enumeration = properties.propertyNames();
                      enumeration.hasMoreElements(); ) {
         String s1 = (String)enumeration.nextElement();
         String s2 = properties.getProperty(s1);
         if (s1.equalsIgnoreCase("user"))
            s1 = "UID";
         if (s1.equalsIgnoreCase("password"))
            s1 = "PWD";
         if (s2 != null)
            s = s + ";" + s1 + "=" + s2;
       }
       return s;
   }
}

