Re: Avoiding explicit addDataType calls for PostGIS - Mailing list pgsql-jdbc

From Oliver Jowett
Subject Re: Avoiding explicit addDataType calls for PostGIS
Date
Msg-id 416B63BF.4090304@opencloud.com
Whole thread Raw
In response to Re: Avoiding explicit addDataType calls for PostGIS  (Markus Schaber <schabios@logi-track.com>)
Responses Re: Avoiding explicit addDataType calls for PostGIS
Re: Avoiding explicit addDataType calls for PostGIS
List pgsql-jdbc
Markus Schaber wrote:
> Hi, Oliver,
>
> On Thu, 07 Oct 2004 10:11:22 +1300
> Oliver Jowett <oliver@opencloud.com> wrote:
>
>>If your objective is to produce a driver that automatically supports
>>the extra datatypes, how about a provider-properties-file approach?
>
> That is a nice idea that allows to control default configuration without
> recompiling, and without explicit code in the app.

Here is a first cut at implementing this.

The driver looks for resources named "postgresql.properties" in its
classloader, loads them as property files in the order the classloader
returns them, and uses the result as default properties. These defaults
are overridden in turn by user-provided properties and properties
extracted from the connection URL.

Properties of the form datatype.<typename>=<classname> cause the given
class to be loaded and registered via addDataType. The default set of
datatypes (interval, money, line, etc) are registered in this way by a
default postgresql.properties included in the driver jar.

I haven't looked at preventing user properties from causing classloading
yet.. don't know if it is worth it.

Also I have not investigated the exact order of resources that
ClassLoader.getResources() returns; it might need some tuning.

-O
Index: org/postgresql/Driver.java.in
===================================================================
RCS file: /usr/local/cvsroot/pgjdbc/pgjdbc/org/postgresql/Driver.java.in,v
retrieving revision 1.48
diff -u -c -r1.48 Driver.java.in
*** org/postgresql/Driver.java.in    10 Oct 2004 15:39:30 -0000    1.48
--- org/postgresql/Driver.java.in    12 Oct 2004 04:35:56 -0000
***************
*** 15,20 ****
--- 15,21 ----
  import java.io.*;
  import java.sql.*;
  import java.util.*;
+ import java.net.URL;

  import org.postgresql.util.PSQLException;
  import org.postgresql.util.PSQLState;
***************
*** 66,71 ****
--- 67,95 ----
          }
      }

+     //
+     // Helper to retrieve default properties from classloader resource
+     // properties files.
+     //
+     private Properties defaultProperties;
+     synchronized Properties getDefaultProperties() throws IOException {
+         if (defaultProperties != null)
+             return defaultProperties;
+
+         Properties merged = new Properties();
+
+         Enumeration urls = getClass().getClassLoader().getResources("postgresql.properties");
+         while (urls.hasMoreElements()) {
+             URL url = (URL)urls.nextElement();
+             InputStream is = url.openStream();
+             merged.load(is);
+             is.close();
+         }
+
+         defaultProperties = merged;
+         return defaultProperties;
+     }
+
      /*
       * Try to make a database connection to the given URL.    The driver
       * should return "null" if it realizes it is the wrong kind of
***************
*** 125,132 ****
       */
      public java.sql.Connection connect(String url, Properties info) throws SQLException
      {
!         Properties props;
!         if ((props = parseURL(url, info)) == null)
          {
              if (Driver.logDebug)
                  Driver.debug("Error in url" + url);
--- 149,172 ----
       */
      public java.sql.Connection connect(String url, Properties info) throws SQLException
      {
!         // get defaults
!         Properties defaults;
!         try {
!             defaults = getDefaultProperties();
!         } catch (IOException ioe) {
!             throw new PSQLException(GT.tr("Error loading default settings from postgresql.properties"),
!                                     PSQLState.UNEXPECTED_ERROR, ioe);
!         }
!
!         // override defaults with provided properties
!         Properties props = new Properties(defaults);
!         for (Enumeration e = info.propertyNames(); e.hasMoreElements(); ) {
!             String propName = (String)e.nextElement();
!             props.put(propName, info.getProperty(propName));
!         }
!
!         // parse URL and add more properties
!         if ((props = parseURL(url, props)) == null)
          {
              if (Driver.logDebug)
                  Driver.debug("Error in url" + url);
Index: org/postgresql/jdbc2/AbstractJdbc2Connection.java
===================================================================
RCS file: /usr/local/cvsroot/pgjdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java,v
retrieving revision 1.18
diff -u -c -r1.18 AbstractJdbc2Connection.java
*** org/postgresql/jdbc2/AbstractJdbc2Connection.java    10 Oct 2004 15:39:40 -0000    1.18
--- org/postgresql/jdbc2/AbstractJdbc2Connection.java    12 Oct 2004 04:35:57 -0000
***************
*** 93,103 ****
          prepareThreshold = 0;
          try {
              prepareThreshold = Integer.parseInt(info.getProperty("prepareThreshold", "0"));
          } catch (Exception e) {}
!
!         if (prepareThreshold < 0)
!             prepareThreshold = 0;
!
          //Print out the driver version number
          if (Driver.logInfo)
              Driver.info(Driver.getVersion());
--- 93,102 ----
          prepareThreshold = 0;
          try {
              prepareThreshold = Integer.parseInt(info.getProperty("prepareThreshold", "0"));
+             if (prepareThreshold < 0)
+                 prepareThreshold = 0;
          } catch (Exception e) {}
!
          //Print out the driver version number
          if (Driver.logInfo)
              Driver.info(Driver.getVersion());
***************
*** 118,124 ****
          rollbackQuery = getQueryExecutor().createSimpleQuery("ROLLBACK");

          // Initialize object handling
!         initObjectTypes();
      }

      /*
--- 117,123 ----
          rollbackQuery = getQueryExecutor().createSimpleQuery("ROLLBACK");

          // Initialize object handling
!         initObjectTypes(info);
      }

      /*
***************
*** 417,444 ****
      // This holds the available types, a String to Class mapping.
      private final HashMap objectTypes = new HashMap();

-     // This array contains the types that are supported as standard.
-     //
-     // The first entry is the types name on the database, the second
-     // the full class name of the handling class.
-     //
-     private static final Object[][] defaultObjectTypes = {
-         { "box",      org.postgresql.geometric.PGbox.class     },
-         { "circle",   org.postgresql.geometric.PGcircle.class  },
-         { "line",     org.postgresql.geometric.PGline.class    },
-         { "lseg",     org.postgresql.geometric.PGlseg.class    },
-         { "path",     org.postgresql.geometric.PGpath.class    },
-         { "point",    org.postgresql.geometric.PGpoint.class   },
-         { "polygon",  org.postgresql.geometric.PGpolygon.class },
-         { "money",    org.postgresql.util.PGmoney.class        },
-         { "interval", org.postgresql.util.PGInterval.class     }
-     };
-
      // This initialises the objectTypes hashtable
!     private void initObjectTypes() throws SQLException
      {
!         for (int i = 0; i < defaultObjectTypes.length; ++i)
!             addDataType((String) defaultObjectTypes[i][0], (Class) defaultObjectTypes[i][1]);
      }

      /**
--- 416,441 ----
      // This holds the available types, a String to Class mapping.
      private final HashMap objectTypes = new HashMap();

      // This initialises the objectTypes hashtable
!     private void initObjectTypes(Properties info) throws SQLException
      {
!         for (Enumeration e = info.propertyNames(); e.hasMoreElements(); ) {
!             String propertyName = (String)e.nextElement();
!             if (propertyName.startsWith("datatype.")) {
!                 String typeName = propertyName.substring(9);
!                 String className = info.getProperty(propertyName);
!                 Class klass;
!
!                 try {
!                     klass = Class.forName(className);
!                 } catch (ClassNotFoundException cnfe) {
!                     throw new PSQLException(GT.tr("Unable to load the class {0} responsible for the datatype {1}",
newObject[] { className, typeName }), 
!                                             PSQLState.SYSTEM_ERROR, cnfe);
!                 }
!
!                 addDataType(typeName, klass);
!             }
!         }
      }

      /**
Index: build.xml
===================================================================
RCS file: /usr/local/cvsroot/pgjdbc/pgjdbc/build.xml,v
retrieving revision 1.52
diff -u -c -r1.52 build.xml
*** build.xml    10 Oct 2004 15:39:29 -0000    1.52
--- build.xml    12 Oct 2004 04:35:57 -0000
***************
*** 105,110 ****
--- 105,111 ----
        </fileset>

        <fileset dir="${srcdir}">
+         <include name="postgresql.properties"/>
          <include name="${package}/translation/*.class" />
        </fileset>
      </jar>
*** /dev/null    Mon Feb  2 17:15:26 2004
--- postgresql.properties    Tue Oct 12 17:08:52 2004
***************
*** 0 ****
--- 1,16 ----
+ #
+ # This property file is included in the driver jar and controls the default
+ # driver settings. These values may be overridden or added to by placing
+ # additional property files (also named 'postgresql.properties') in the
+ # driver's classpath.
+ #
+ prepareThreshold=5
+ datatype.box=org.postgresql.geometric.PGbox
+ datatype.circle=org.postgresql.geometric.PGcircle
+ datatype.line=org.postgresql.geometric.PGline
+ datatype.lseg=org.postgresql.geometric.PGlseg
+ datatype.path=org.postgresql.geometric.PGpath
+ datatype.point=org.postgresql.geometric.PGpoint
+ datatype.polygon=org.postgresql.geometric.PGpolygon
+ datatype.money=org.postgresql.util.PGmoney
+ datatype.interval=org.postgresql.util.PGInterval

pgsql-jdbc by date:

Previous
From: Oliver Jowett
Date:
Subject: Re: A solution to the SSL customizing problem
Next
From: Ulrich Meis
Date:
Subject: Re: A solution to the SSL customizing problem