diff options
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/Driver.java.in')
-rw-r--r-- | src/interfaces/jdbc/org/postgresql/Driver.java.in | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in new file mode 100644 index 0000000000..40e2a94956 --- /dev/null +++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in @@ -0,0 +1,381 @@ +package org.postgresql; + +import java.sql.*; +import java.util.*; + +import org.postgresql.util.PSQLException; + +/** + * The Java SQL framework allows for multiple database drivers. Each + * driver should supply a class that implements the Driver interface + * + * <p>The DriverManager will try to load as many drivers as it can find and + * then for any given connection request, it will ask each driver in turn + * to try to connect to the target URL. + * + * <p>It is strongly recommended that each Driver class should be small and + * standalone so that the Driver class can be loaded and queried without + * bringing in vast quantities of supporting code. + * + * <p>When a Driver class is loaded, it should create an instance of itself + * and register it with the DriverManager. This means that a user can load + * and register a driver by doing Class.forName("foo.bah.Driver") + * + * @see org.postgresql.Connection + * @see java.sql.Driver + */ +public class Driver implements java.sql.Driver +{ + + static + { + try { + // moved the registerDriver from the constructor to here + // because some clients call the driver themselves (I know, as + // my early jdbc work did - and that was based on other examples). + // Placing it here, means that the driver is registered once only. + java.sql.DriverManager.registerDriver(new Driver()); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * Construct a new driver and register it with DriverManager + * + * @exception SQLException for who knows what! + */ + public Driver() throws SQLException + { + // Set the connectClass variable so that future calls will handle the correct + // base class + //if(System.getProperty("java.version").startsWith("1.1")) { + //connectClass = "postgresql.jdbc1.Connection"; + //} else { + //connectClass = "postgresql.jdbc2.Connection"; + //} + + // Ok, when the above code was introduced in 6.5 it's intention was to allow + // the driver to automatically detect which version of JDBC was being used + // and to detect the version of the JVM accordingly. + // + // It did this by using the java.version parameter. + // + // However, it was quickly discovered that not all JVM's returned an easily + // parseable version number (ie "1.2") and some don't return a value at all. + // The latter came from a discussion on the advanced java list. + // + // So, to solve this, I've moved the decision out of the driver, and it's now + // a compile time parameter. + // + // For this to work, the Makefile creates a pseudo class which contains the class + // name that will actually make the connection. + } + + /** + * Try to make a database connection to the given URL. The driver + * should return "null" if it realizes it is the wrong kind of + * driver to connect to the given URL. This will be common, as + * when the JDBC driverManager is asked to connect to a given URL, + * it passes the URL to each loaded driver in turn. + * + * <p>The driver should raise an SQLException if it is the right driver + * to connect to the given URL, but has trouble connecting to the + * database. + * + * <p>The java.util.Properties argument can be used to pass arbitrary + * string tag/value pairs as connection arguments. Normally, at least + * "user" and "password" properties should be included in the + * properties. In addition, the "charSet" property can be used to + * set a character set encoding (e.g. "utf-8") other than the platform + * default (typically Latin1). This is necessary in particular if storing + * multibyte characters in the database. For a list of supported + * character encoding , see + * http://java.sun.com/products/jdk/1.2/docs/guide/internat/encoding.doc.html + * Note that you will probably want to have set up the Postgres database + * itself to use the same encoding, with the "-E <encoding>" argument + * to createdb. + * + * Our protocol takes the forms: + * <PRE> + * jdbc:org.postgresql://host:port/database?param1=val1&... + * </PRE> + * + * @param url the URL of the database to connect to + * @param info a list of arbitrary tag/value pairs as connection + * arguments + * @return a connection to the URL or null if it isnt us + * @exception SQLException if a database access error occurs + * @see java.sql.Driver#connect + */ + public java.sql.Connection connect(String url, Properties info) throws SQLException + { + if((props = parseURL(url,info))==null) + return null; + + try { + org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName("%JDBCCONNECTCLASS%").newInstance()); + con.openConnection (host(), port(), props, database(), url, this); + return (java.sql.Connection)con; + } catch(ClassNotFoundException ex) { + throw new PSQLException("postgresql.jvm.version",ex); + } catch(PSQLException ex1) { + // re-throw the exception, otherwise it will be caught next, and a + // org.postgresql.unusual error will be returned instead. + throw ex1; + } catch(Exception ex2) { + throw new PSQLException("postgresql.unusual",ex2); + } + } + + /** + * Returns true if the driver thinks it can open a connection to the + * given URL. Typically, drivers will return true if they understand + * the subprotocol specified in the URL and false if they don't. Our + * protocols start with jdbc:org.postgresql: + * + * @see java.sql.Driver#acceptsURL + * @param url the URL of the driver + * @return true if this driver accepts the given URL + * @exception SQLException if a database-access error occurs + * (Dont know why it would *shrug*) + */ + public boolean acceptsURL(String url) throws SQLException + { + if(parseURL(url,null)==null) + return false; + return true; + } + + /** + * The getPropertyInfo method is intended to allow a generic GUI + * tool to discover what properties it should prompt a human for + * in order to get enough information to connect to a database. + * + * <p>Note that depending on the values the human has supplied so + * far, additional values may become necessary, so it may be necessary + * to iterate through several calls to getPropertyInfo + * + * @param url the Url of the database to connect to + * @param info a proposed list of tag/value pairs that will be sent on + * connect open. + * @return An array of DriverPropertyInfo objects describing + * possible properties. This array may be an empty array if + * no properties are required + * @exception SQLException if a database-access error occurs + * @see java.sql.Driver#getPropertyInfo + */ + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException + { + Properties p = parseURL(url,info); + + // naughty, but its best for speed. If anyone adds a property here, then + // this _MUST_ be increased to accomodate them. + DriverPropertyInfo d,dpi[] = new DriverPropertyInfo[0]; + //int i=0; + + //dpi[i++] = d = new DriverPropertyInfo("auth",p.getProperty("auth","default")); + //d.description = "determines if password authentication is used"; + //d.choices = new String[4]; + //d.choices[0]="default"; // Get value from org.postgresql.auth property, defaults to trust + //d.choices[1]="trust"; // No password authentication + //d.choices[2]="password"; // Password authentication + //d.choices[3]="ident"; // Ident (RFC 1413) protocol + + return dpi; + } + + /** + * Gets the drivers major version number + * + * @return the drivers major version number + */ + public int getMajorVersion() + { + return %MAJORVERSION%; + } + + /** + * Get the drivers minor version number + * + * @return the drivers minor version number + */ + public int getMinorVersion() + { + return %MINORVERSION%; + } + + /** + * Returns the VERSION variable from Makefile.global + */ + public static String getVersion() + { + return "%VERSION%"; + } + + /** + * Report whether the driver is a genuine JDBC compliant driver. A + * driver may only report "true" here if it passes the JDBC compliance + * tests, otherwise it is required to return false. JDBC compliance + * requires full support for the JDBC API and full support for SQL 92 + * Entry Level. + * + * <p>For PostgreSQL, this is not yet possible, as we are not SQL92 + * compliant (yet). + */ + public boolean jdbcCompliant() + { + return false; + } + + private Properties props; + + static private String[] protocols = { "jdbc","postgresql" }; + + /** + * Constructs a new DriverURL, splitting the specified URL into its + * component parts + * @param url JDBC URL to parse + * @param defaults Default properties + * @return Properties with elements added from the url + * @exception SQLException + */ + Properties parseURL(String url,Properties defaults) throws SQLException + { + int state = -1; + Properties urlProps = new Properties(defaults); + String key = ""; + String value = ""; + + StringTokenizer st = new StringTokenizer(url, ":/;=&?", true); + for (int count = 0; (st.hasMoreTokens()); count++) { + String token = st.nextToken(); + + // PM June 29 1997 + // Added this, to help me understand how this works. + // Unless you want each token to be processed, leave this commented out + // but don't delete it. + //DriverManager.println("wellFormedURL: state="+state+" count="+count+" token='"+token+"'"); + + // PM Aug 2 1997 - Modified to allow multiple backends + if (count <= 3) { + if ((count % 2) == 1 && token.equals(":")) + ; + else if((count % 2) == 0) { + boolean found=(count==0)?true:false; + for(int tmp=0;tmp<protocols.length;tmp++) { + if(token.equals(protocols[tmp])) { + // PM June 29 1997 Added this property to enable the driver + // to handle multiple backend protocols. + if(count == 2 && tmp > 0) { + urlProps.put("Protocol",token); + found=true; + } + } + } + + if(found == false) + return null; + } else return null; + } + else if (count > 3) { + if (count == 4 && token.equals("/")) state = 0; + else if (count == 4) { + urlProps.put("PGDBNAME", token); + state = -2; + } + else if (count == 5 && state == 0 && token.equals("/")) + state = 1; + else if (count == 5 && state == 0) + return null; + else if (count == 6 && state == 1) + urlProps.put("PGHOST", token); + else if (count == 7 && token.equals(":")) state = 2; + else if (count == 8 && state == 2) { + try { + Integer portNumber = Integer.decode(token); + urlProps.put("PGPORT", portNumber.toString()); + } catch (Exception e) { + return null; + } + } + else if ((count == 7 || count == 9) && + (state == 1 || state == 2) && token.equals("/")) + state = -1; + else if (state == -1) { + urlProps.put("PGDBNAME", token); + state = -2; + } + else if (state <= -2 && (count % 2) == 1) { + // PM Aug 2 1997 - added tests for ? and & + if (token.equals(";") || token.equals("?") || token.equals("&") ) state = -3; + else if (token.equals("=")) state = -5; + } + else if (state <= -2 && (count % 2) == 0) { + if (state == -3) key = token; + else if (state == -5) { + value = token; + //DriverManager.println("put("+key+","+value+")"); + urlProps.put(key, value); + state = -2; + } + } + } + } + + // PM June 29 1997 + // This now outputs the properties only if we are logging + // PM Sep 13 1999 Commented out, as it throws a Deprecation warning + // when compiled under JDK1.2. + //if(DriverManager.getLogStream() != null) + // urlProps.list(DriverManager.getLogStream()); + + return urlProps; + + } + + /** + * @return the hostname portion of the URL + */ + public String host() + { + return props.getProperty("PGHOST","localhost"); + } + + /** + * @return the port number portion of the URL or -1 if no port was specified + */ + public int port() + { + return Integer.parseInt(props.getProperty("PGPORT","5432")); + } + + /** + * @return the database name of the URL + */ + public String database() + { + return props.getProperty("PGDBNAME"); + } + + /** + * @return the value of any property specified in the URL or properties + * passed to connect(), or null if not found. + */ + public String property(String name) + { + return props.getProperty(name); + } + + /** + * This method was added in v6.5, and simply throws an SQLException + * for an unimplemented method. I decided to do it this way while + * implementing the JDBC2 extensions to JDBC, as it should help keep the + * overall driver size down. + */ + public static SQLException notImplemented() + { + return new PSQLException("postgresql.unimplemented"); + } +} + |