If anyone feels like tackeling this one here's the code which I've got so far. It doesn't actually work and it could well be completely the wrong way to go about this.
It shouldn't break any existing code but if you add a classpath attribute to the SQL task it will attempt to use it and then fall over with an IllegalAcessException. I'd be very interested to see if anyone can get this to work, but since I can still use the glabal classpath to load the drivers from it's not essential, it would just be nice to have it. Tah ;o) -----Original Message----- From: John Lacey [mailto:[EMAIL PROTECTED] Sent: 16 August 2000 03:22 To: [EMAIL PROTECTED] Subject: Re: AntClassLoader and JDBC drivers Conor MacNeill wrote: > > The driver you are actually loading is a class which implements the Driver > interface, so there should be no problem in loading it and creating an > instance. This is true of the Oracle driver we use here. It's true of most drivers, due to the Microsoft JVM, which didn't originally interpret Class.forName as requiring class initialization. (The requirement has been clarified, and later MS JVMs respect the requirement.) The workaround was Class.forName(...).newInstance(), which requires a public no-args constructor. It is not required, however, for JDBC drivers to have any public constructors at all. Java 2 has the nice Class.forName(String, boolean, ClassLoader), which is probably off-limits, alas. [EMAIL PROTECTED] wrote: > > Another approach that is useful is to get reference to class > and try to look up a non-existent method. This forces > resolution (usually). I don't see that this is required to work, either, but it seems like a reasonable followup to trying newInstance (which for most practical purposes will work). (For the pedantically inclined, my reading of 12.4.1 suggests that reflective methods should only cause class initialization when a corresponding non-reflective action would have, i.e., instance creation, method invocation, or field access.) Jeff Martin wrote: > > I tried to create a wrapper class which I could > load via the AntClassLoader but just ended up getting > IllegalAccessExceptions so I've given up. This seems like the best by-the-book JDK 1.1-compatible approach. I'm assuming that your wrapper class just calls Class.forName. Why don't you post the code for your wrapper if you aren't happy with the workarounds. John L
Index: src/main/org/apache/tools/ant/taskdefs/SQLExec.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/SQLExec.java,v
retrieving revision 1.5
diff -r1.5 SQLExec.java
57a58
> import org.apache.tools.ant.types.*;
73a75,78
> /**
> * Classpath for loading JDBC drivers
> */
> private Path classpath = null;
120a126,132
> * Set the classpath to be used for this compilation.
> */
> public void setClasspath(Path classpath) {
> this.classpath = classpath;
> }
>
> /**
194a207
> ConnectionLoader connLoader=null;
196c209,224
< Class.forName(driver);
---
> if(classpath==null){
> Class.forName(driver);
> }else{
> log("Loading jdbc driver "+ driver + " from classpath " +
> classpath, Project.MSG_VERBOSE);
> connLoader = (ConnectionLoader)new AntClassLoader(project,
> classpath).loadClass("org.apache.tools.ant.tasks.SQLExecConnection").newInstance();
> conn = connLoader.getConnection(driver, url, userId,
> password);
> }
> }catch(SQLException e){
> e.printStackTrace();
> throw new BuildException("JDBC driver " + driver + " could not be
> loaded", location);
> }catch(InstantiationException e){
> e.printStackTrace();
> throw new BuildException("JDBC driver " + driver + " could not be
> loaded", location);
> }catch(IllegalAccessException e){
> e.printStackTrace();
> throw new BuildException("JDBC driver " + driver + " could not be
> loaded", location);
197a226
> e.printStackTrace();
203c232,234
< conn = DriverManager.getConnection(url, userId, password);
---
> if(connLoader==null){
> conn = DriverManager.getConnection(url, userId, password);
> }
250a282,285
> public static interface ConnectionLoader{
> public Connection getConnection(String driver, String url, String
> userId, String password) throws SQLException, ClassNotFoundException;
> }
>
SQLExecConnection.java
Description: Binary data
