Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4fc3690

Browse files
author
Peter Mount
committed
Attempt III
1 parent 39116bf commit 4fc3690

File tree

9 files changed

+1980
-0
lines changed

9 files changed

+1980
-0
lines changed

src/interfaces/jdbc/org/postgresql/Connection.java

+752
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
package org.postgresql;
2+
3+
import java.sql.*;
4+
import java.util.*;
5+
6+
import org.postgresql.util.PSQLException;
7+
8+
/**
9+
* The Java SQL framework allows for multiple database drivers. Each
10+
* driver should supply a class that implements the Driver interface
11+
*
12+
* <p>The DriverManager will try to load as many drivers as it can find and
13+
* then for any given connection request, it will ask each driver in turn
14+
* to try to connect to the target URL.
15+
*
16+
* <p>It is strongly recommended that each Driver class should be small and
17+
* standalone so that the Driver class can be loaded and queried without
18+
* bringing in vast quantities of supporting code.
19+
*
20+
* <p>When a Driver class is loaded, it should create an instance of itself
21+
* and register it with the DriverManager. This means that a user can load
22+
* and register a driver by doing Class.forName("foo.bah.Driver")
23+
*
24+
* @see org.postgresql.Connection
25+
* @see java.sql.Driver
26+
*/
27+
public class Driver implements java.sql.Driver
28+
{
29+
// These should be in sync with the backend that the driver was
30+
// distributed with
31+
static final int MAJORVERSION = 7;
32+
static final int MINORVERSION = 0;
33+
34+
static
35+
{
36+
try {
37+
// moved the registerDriver from the constructor to here
38+
// because some clients call the driver themselves (I know, as
39+
// my early jdbc work did - and that was based on other examples).
40+
// Placing it here, means that the driver is registered once only.
41+
java.sql.DriverManager.registerDriver(new Driver());
42+
} catch (SQLException e) {
43+
e.printStackTrace();
44+
}
45+
}
46+
47+
/**
48+
* Construct a new driver and register it with DriverManager
49+
*
50+
* @exception SQLException for who knows what!
51+
*/
52+
public Driver() throws SQLException
53+
{
54+
// Set the connectClass variable so that future calls will handle the correct
55+
// base class
56+
//if(System.getProperty("java.version").startsWith("1.1")) {
57+
//connectClass = "postgresql.jdbc1.Connection";
58+
//} else {
59+
//connectClass = "postgresql.jdbc2.Connection";
60+
//}
61+
62+
// Ok, when the above code was introduced in 6.5 it's intention was to allow
63+
// the driver to automatically detect which version of JDBC was being used
64+
// and to detect the version of the JVM accordingly.
65+
//
66+
// It did this by using the java.version parameter.
67+
//
68+
// However, it was quickly discovered that not all JVM's returned an easily
69+
// parseable version number (ie "1.2") and some don't return a value at all.
70+
// The latter came from a discussion on the advanced java list.
71+
//
72+
// So, to solve this, I've moved the decision out of the driver, and it's now
73+
// a compile time parameter.
74+
//
75+
// For this to work, the Makefile creates a pseudo class which contains the class
76+
// name that will actually make the connection.
77+
}
78+
79+
/**
80+
* Try to make a database connection to the given URL. The driver
81+
* should return "null" if it realizes it is the wrong kind of
82+
* driver to connect to the given URL. This will be common, as
83+
* when the JDBC driverManager is asked to connect to a given URL,
84+
* it passes the URL to each loaded driver in turn.
85+
*
86+
* <p>The driver should raise an SQLException if it is the right driver
87+
* to connect to the given URL, but has trouble connecting to the
88+
* database.
89+
*
90+
* <p>The java.util.Properties argument can be used to pass arbitrary
91+
* string tag/value pairs as connection arguments. Normally, at least
92+
* "user" and "password" properties should be included in the
93+
* properties.
94+
*
95+
* Our protocol takes the forms:
96+
* <PRE>
97+
* jdbc:org.postgresql://host:port/database?param1=val1&...
98+
* </PRE>
99+
*
100+
* @param url the URL of the database to connect to
101+
* @param info a list of arbitrary tag/value pairs as connection
102+
* arguments
103+
* @return a connection to the URL or null if it isnt us
104+
* @exception SQLException if a database access error occurs
105+
* @see java.sql.Driver#connect
106+
*/
107+
public java.sql.Connection connect(String url, Properties info) throws SQLException
108+
{
109+
if((props = parseURL(url,info))==null)
110+
return null;
111+
112+
DriverManager.println("Using "+DriverClass.connectClass);
113+
114+
try {
115+
org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName(DriverClass.connectClass).newInstance());
116+
con.openConnection (host(), port(), props, database(), url, this);
117+
return (java.sql.Connection)con;
118+
} catch(ClassNotFoundException ex) {
119+
throw new PSQLException("postgresql.jvm.version",ex);
120+
} catch(PSQLException ex1) {
121+
// re-throw the exception, otherwise it will be caught next, and a
122+
// org.postgresql.unusual error will be returned instead.
123+
throw ex1;
124+
} catch(Exception ex2) {
125+
throw new PSQLException("postgresql.unusual",ex2);
126+
}
127+
}
128+
129+
/**
130+
* Returns true if the driver thinks it can open a connection to the
131+
* given URL. Typically, drivers will return true if they understand
132+
* the subprotocol specified in the URL and false if they don't. Our
133+
* protocols start with jdbc:org.postgresql:
134+
*
135+
* @see java.sql.Driver#acceptsURL
136+
* @param url the URL of the driver
137+
* @return true if this driver accepts the given URL
138+
* @exception SQLException if a database-access error occurs
139+
* (Dont know why it would *shrug*)
140+
*/
141+
public boolean acceptsURL(String url) throws SQLException
142+
{
143+
if(parseURL(url,null)==null)
144+
return false;
145+
return true;
146+
}
147+
148+
/**
149+
* The getPropertyInfo method is intended to allow a generic GUI
150+
* tool to discover what properties it should prompt a human for
151+
* in order to get enough information to connect to a database.
152+
*
153+
* <p>Note that depending on the values the human has supplied so
154+
* far, additional values may become necessary, so it may be necessary
155+
* to iterate through several calls to getPropertyInfo
156+
*
157+
* @param url the Url of the database to connect to
158+
* @param info a proposed list of tag/value pairs that will be sent on
159+
* connect open.
160+
* @return An array of DriverPropertyInfo objects describing
161+
* possible properties. This array may be an empty array if
162+
* no properties are required
163+
* @exception SQLException if a database-access error occurs
164+
* @see java.sql.Driver#getPropertyInfo
165+
*/
166+
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
167+
{
168+
Properties p = parseURL(url,info);
169+
170+
// naughty, but its best for speed. If anyone adds a property here, then
171+
// this _MUST_ be increased to accomodate them.
172+
DriverPropertyInfo d,dpi[] = new DriverPropertyInfo[0];
173+
//int i=0;
174+
175+
//dpi[i++] = d = new DriverPropertyInfo("auth",p.getProperty("auth","default"));
176+
//d.description = "determines if password authentication is used";
177+
//d.choices = new String[4];
178+
//d.choices[0]="default"; // Get value from org.postgresql.auth property, defaults to trust
179+
//d.choices[1]="trust"; // No password authentication
180+
//d.choices[2]="password"; // Password authentication
181+
//d.choices[3]="ident"; // Ident (RFC 1413) protocol
182+
183+
return dpi;
184+
}
185+
186+
/**
187+
* Gets the drivers major version number
188+
*
189+
* @return the drivers major version number
190+
*/
191+
public int getMajorVersion()
192+
{
193+
return MAJORVERSION;
194+
}
195+
196+
/**
197+
* Get the drivers minor version number
198+
*
199+
* @return the drivers minor version number
200+
*/
201+
public int getMinorVersion()
202+
{
203+
return MINORVERSION;
204+
}
205+
206+
/**
207+
* Report whether the driver is a genuine JDBC compliant driver. A
208+
* driver may only report "true" here if it passes the JDBC compliance
209+
* tests, otherwise it is required to return false. JDBC compliance
210+
* requires full support for the JDBC API and full support for SQL 92
211+
* Entry Level.
212+
*
213+
* <p>For PostgreSQL, this is not yet possible, as we are not SQL92
214+
* compliant (yet).
215+
*/
216+
public boolean jdbcCompliant()
217+
{
218+
return false;
219+
}
220+
221+
private Properties props;
222+
223+
static private String[] protocols = { "jdbc","postgresql" };
224+
225+
/**
226+
* Constructs a new DriverURL, splitting the specified URL into its
227+
* component parts
228+
* @param url JDBC URL to parse
229+
* @param defaults Default properties
230+
* @return Properties with elements added from the url
231+
* @exception SQLException
232+
*/
233+
Properties parseURL(String url,Properties defaults) throws SQLException
234+
{
235+
int state = -1;
236+
Properties urlProps = new Properties(defaults);
237+
String key = new String();
238+
String value = new String();
239+
240+
StringTokenizer st = new StringTokenizer(url, ":/;=&?", true);
241+
for (int count = 0; (st.hasMoreTokens()); count++) {
242+
String token = st.nextToken();
243+
244+
// PM June 29 1997
245+
// Added this, to help me understand how this works.
246+
// Unless you want each token to be processed, leave this commented out
247+
// but don't delete it.
248+
//DriverManager.println("wellFormedURL: state="+state+" count="+count+" token='"+token+"'");
249+
250+
// PM Aug 2 1997 - Modified to allow multiple backends
251+
if (count <= 3) {
252+
if ((count % 2) == 1 && token.equals(":"))
253+
;
254+
else if((count % 2) == 0) {
255+
boolean found=(count==0)?true:false;
256+
for(int tmp=0;tmp<protocols.length;tmp++) {
257+
if(token.equals(protocols[tmp])) {
258+
// PM June 29 1997 Added this property to enable the driver
259+
// to handle multiple backend protocols.
260+
if(count == 2 && tmp > 0) {
261+
urlProps.put("Protocol",token);
262+
found=true;
263+
}
264+
}
265+
}
266+
267+
if(found == false)
268+
return null;
269+
} else return null;
270+
}
271+
else if (count > 3) {
272+
if (count == 4 && token.equals("/")) state = 0;
273+
else if (count == 4) {
274+
urlProps.put("PGDBNAME", token);
275+
state = -2;
276+
}
277+
else if (count == 5 && state == 0 && token.equals("/"))
278+
state = 1;
279+
else if (count == 5 && state == 0)
280+
return null;
281+
else if (count == 6 && state == 1)
282+
urlProps.put("PGHOST", token);
283+
else if (count == 7 && token.equals(":")) state = 2;
284+
else if (count == 8 && state == 2) {
285+
try {
286+
Integer portNumber = Integer.decode(token);
287+
urlProps.put("PGPORT", portNumber.toString());
288+
} catch (Exception e) {
289+
return null;
290+
}
291+
}
292+
else if ((count == 7 || count == 9) &&
293+
(state == 1 || state == 2) && token.equals("/"))
294+
state = -1;
295+
else if (state == -1) {
296+
urlProps.put("PGDBNAME", token);
297+
state = -2;
298+
}
299+
else if (state <= -2 && (count % 2) == 1) {
300+
// PM Aug 2 1997 - added tests for ? and &
301+
if (token.equals(";") || token.equals("?") || token.equals("&") ) state = -3;
302+
else if (token.equals("=")) state = -5;
303+
}
304+
else if (state <= -2 && (count % 2) == 0) {
305+
if (state == -3) key = token;
306+
else if (state == -5) {
307+
value = token;
308+
//DriverManager.println("put("+key+","+value+")");
309+
urlProps.put(key, value);
310+
state = -2;
311+
}
312+
}
313+
}
314+
}
315+
316+
// PM June 29 1997
317+
// This now outputs the properties only if we are logging
318+
// PM Sep 13 1999 Commented out, as it throws a Deprecation warning
319+
// when compiled under JDK1.2.
320+
//if(DriverManager.getLogStream() != null)
321+
// urlProps.list(DriverManager.getLogStream());
322+
323+
return urlProps;
324+
325+
}
326+
327+
/**
328+
* @return the hostname portion of the URL
329+
*/
330+
public String host()
331+
{
332+
return props.getProperty("PGHOST","localhost");
333+
}
334+
335+
/**
336+
* @return the port number portion of the URL or -1 if no port was specified
337+
*/
338+
public int port()
339+
{
340+
return Integer.parseInt(props.getProperty("PGPORT","5432"));
341+
}
342+
343+
/**
344+
* @return the database name of the URL
345+
*/
346+
public String database()
347+
{
348+
return props.getProperty("PGDBNAME");
349+
}
350+
351+
/**
352+
* @return the value of any property specified in the URL or properties
353+
* passed to connect(), or null if not found.
354+
*/
355+
public String property(String name)
356+
{
357+
return props.getProperty(name);
358+
}
359+
360+
/**
361+
* This method was added in v6.5, and simply throws an SQLException
362+
* for an unimplemented method. I decided to do it this way while
363+
* implementing the JDBC2 extensions to JDBC, as it should help keep the
364+
* overall driver size down.
365+
*/
366+
public static SQLException notImplemented()
367+
{
368+
return new PSQLException("postgresql.unimplemented");
369+
}
370+
}
371+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.postgresql;
2+
public class DriverClass {
3+
public static String connectClass="org.postgresql.jdbc2.Connection";
4+
}

0 commit comments

Comments
 (0)