You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ba...@apache.org on 2003/03/08 21:35:05 UTC
cvs commit: jakarta-commons-sandbox/dbutils/src/test/org/apache/commons/dbutils Demo.java ProcedureUtilsTest.java
baliuka 2003/03/08 12:35:05
Modified: dbutils/src/java/org/apache/commons/dbutils DbUtils.java
ProcedureUtils.java
Added: dbutils/src/java/org/apache/commons/dbutils
ResultSetHandler.java ScalarHandler.java
dbutils/src/test connection.properties
dbutils/src/test/org/apache/commons/dbutils Demo.java
ProcedureUtilsTest.java
Log:
added dependancy on Qdox
Revision Changes Path
1.11 +1 -5 jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/DbUtils.java
Index: DbUtils.java
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/DbUtils.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- DbUtils.java 6 Mar 2003 18:47:35 -0000 1.10
+++ DbUtils.java 8 Mar 2003 20:35:05 -0000 1.11
@@ -64,11 +64,7 @@
public final class DbUtils {
- public static interface ResultSetHandler{
-
- public Object handle(ResultSet rs)throws SQLException;
-
- }
+
public static abstract class ListAdapter extends ArrayList implements ResultSetHandler{
final public Object handle(ResultSet rs)throws SQLException{
1.2 +261 -145 jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ProcedureUtils.java
Index: ProcedureUtils.java
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ProcedureUtils.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ProcedureUtils.java 6 Mar 2003 18:47:35 -0000 1.1
+++ ProcedureUtils.java 8 Mar 2003 20:35:05 -0000 1.2
@@ -60,31 +60,36 @@
import java.util.*;
import java.lang.reflect.*;
import java.sql.*;
+import java.io.*;
+
+import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.model.*;
+
/**
* sample:
* class DAO {
*
* static interface Procedure{
- * int execute(int p1);
+ * int execute(int p1);
* }
*
* static interface Procedure2{
- * int execute2(int p1, int p2);
+ * int execute2(int p1, int p2);
* }
*
* static private scalarProc(Class cls, String sql){
* ProcedureUtils.register(cls, sql, new ScalarHandlerImpl() );
- *
+ *
* }
* static{
*
* scalarProc(Procedure.class,
- * "SELECT COUNT(*) FROM MY_TABLE WHERE VALUE < $1"
+ * "SELECT COUNT(*) FROM MY_TABLE WHERE VALUE < $1"
* );
- *
+ *
* salarProc(Procedure.class,
- * "SELECT SUM(VALUE) - $2 FROM MY_TABLE WHERE VALUE > $1"
- *
+ * "SELECT SUM(VALUE) - $2 FROM MY_TABLE WHERE VALUE > $1"
+ *
* );
* }
*
@@ -98,38 +103,40 @@
* currentConnection());
* }
*
- *
+ *
* public static int main( String args ){
- *
+ *
* System.out.println(getProcedure().execute(0) + getProcedure2().execute(1,3));
- *
+ *
* }
* }
- *
+ *
* TODO:
*
* interface MyDAO{
*
- * @sql SELECT MAX(VALUE) FROM MY_TABLE WHERE VALUE < $1
- * int getMaxLesThan(int p1);
+ * @sql SELECT MAX(VALUE) FROM MY_TABLE WHERE VALUE < $1
+ * int getMaxLesThan(int p1);
*
- * @sql SELECT COUNT(*) FROM MY_TABLE WHERE VALUE < $1 and VALUE >= $2
- * int getCount(int p1, int p2);
+ * @sql SELECT COUNT(*) FROM MY_TABLE WHERE VALUE < $1 and VALUE >= $2
+ * int getCount(int p1, int p2);
* }
- *
+ *
*
* @author baliuka
*/
public final class ProcedureUtils {
private static final Map PROCEDURES = new HashMap();
+ private static final Map PREDEFINED_HANDLERS = new HashMap();
+ private static final ResultSetHandler SCALAR_HANDLER = new ScalarHandler();
static class ProcedureDescriptor{
String jdbcSQL;
int indexMap[];
- DbUtils.ResultSetHandler handler;
+ ResultSetHandler handler;
boolean update;
//TODO:
boolean cached;
@@ -142,9 +149,8 @@
}
- private static ProcedureDescriptor compile(Class procInterface, String sqlStr,
- DbUtils.ResultSetHandler handler,boolean update){
-
+ private static ProcedureDescriptor compile(Method proc, String sqlStr,
+ ResultSetHandler handler,boolean update){
java.util.ArrayList indexes = new java.util.ArrayList();
char sql[] = sqlStr.toCharArray();
@@ -156,26 +162,13 @@
for (int i = 0; i < sql.length; i++ ){
- if(sql[i] == '\''){
-
- escape = false;
- arg = false;
-
- while( true ){
- try{
- sb.append(sql[i++]);
- if(sql[i] == '\'' && sql[i - 1] != '\\'){
- sb.append('\'');
- break;
- }
- }catch(ArrayIndexOutOfBoundsException aie){
- throw new IllegalArgumentException("unterminated string in query");
- }
- }
- continue;
- }
if(sql[i] == '$'){
+ if(escape && !arg){
+ escape = false;
+ arg = false;
+ continue;
+ }
escape = true;
arg = false;
continue;
@@ -184,8 +177,11 @@
if (Character.isDigit(sql[i]) && escape){
digit.append(sql[i]);
arg = true;
- if( i != sql.length - 1 )
+ if( i != sql.length - 1 ){
continue;
+ }else {
+ i++;
+ }
}
if(arg){
@@ -193,52 +189,53 @@
sb.append('?');
digit.delete(0, digit.length() );
}
-
- sb.append(sql[i]);
+ if( i < sql.length ){
+ sb.append(sql[i]);
+ }
escape = false;
arg = false;
}
-
-
-
- Method methods[] = procInterface.getDeclaredMethods();
-
- if(methods.length != 1 ){
- throw new IllegalArgumentException( procInterface.getName() +
- " must declare singe method" );
- }
-
- if(update && ( methods[0].getReturnType() != Void.TYPE || methods[0].getReturnType() != Integer.TYPE )){
-
- throw new IllegalArgumentException( "update method " + methods[0] +
- " must return int or void " );
-
-
- }
-
- for( int i = 0; i < methods[0].getParameterTypes().length; i++ ){
- if(!indexes.contains(new Integer( i + 1))){
- throw new IllegalArgumentException( "missing prameter " +
- methods[0].getParameterTypes() + " $" + (i + 1 ) );
- }
+
+ if( update && proc.getReturnType() != Void.TYPE && proc.getReturnType() != Integer.TYPE ){
+
+ throw new IllegalArgumentException( "update method " + proc +
+ " must return int or void " );
+
+
+ }
+
+ for( int i = 0; i < proc.getParameterTypes().length; i++ ){
+ if(!indexes.contains(new Integer( i + 1))){
+
+ throw new IllegalArgumentException( "missing prameter " +
+ proc.getParameterTypes()[i] + " $" + (i + 1 ) + " in " + proc );
+ }
}
-
-
- ProcedureDescriptor descriptor = new ProcedureDescriptor();
- if(indexes.size() > 0){
-
- int indexMap[] = new int[indexes.size()];
+ for( Iterator i = indexes.iterator(); i.hasNext(); ){
+ int param = ((Number)i.next()).intValue();
+ if(param == 0 || param > proc.getParameterTypes().length ){
+ throw new IllegalArgumentException( "extra prameter " +
+ i + " in " + proc);
+ }
- for( int i = 0 ; i < indexMap.length; i++ ){
- indexMap[i] = ((Integer)indexes.get(i)).intValue() - 1;
}
- descriptor.indexMap = indexMap;
- }else {
- descriptor.indexMap = new int[0];
- }
+ ProcedureDescriptor descriptor = new ProcedureDescriptor();
+ if(indexes.size() > 0){
+
+
+ int indexMap[] = new int[indexes.size()];
+
+ for( int i = 0 ; i < indexMap.length; i++ ){
+ indexMap[i] = ((Integer)indexes.get(i)).intValue() - 1;
+ }
+ descriptor.indexMap = indexMap;
+
+ }else {
+ descriptor.indexMap = new int[0];
+ }
descriptor.handler = handler;
descriptor.jdbcSQL = sb.toString();
@@ -247,86 +244,205 @@
return descriptor;
}
- private static void register( Class procInterface, String sql,
- DbUtils.ResultSetHandler handler){
- if(handler == null){
- throw new NullPointerException("handler is null");
- }
- register( procInterface, sql, handler, false);
+ private static void register( Method proc, String sql,
+ ResultSetHandler handler){
+ if(handler == null){
+ throw new NullPointerException("handler is null");
+ }
+ register( proc, sql, handler, false);
}
- private static void register( Class procInterface, String sql){
- register( procInterface, sql, null, false);
+ private static void register(Method proc, String sql){
+ register( proc, sql, null, false);
}
-
- private static void register( Class procInterface, String sql,
- DbUtils.ResultSetHandler handler, boolean update ){
- if(!procInterface.isInterface()){
- throw new IllegalArgumentException(procInterface.getName() + " is not an interface");
- }
- ProcedureDescriptor des = compile(procInterface,sql, handler, update );
- PROCEDURES.put(procInterface,des);
+
+ private static void register( Method proc, String sql,
+ ResultSetHandler handler, boolean update ){
+ if(!proc.getDeclaringClass().isInterface()){
+ throw new IllegalArgumentException(proc.getDeclaringClass().getName() + " is not an interface");
+ }
+ ProcedureDescriptor des = compile(proc,sql, handler, update );
+ PROCEDURES.put(proc,des);
}
-
- public static Object getInstance(Class cls,Connection connection){
-
- ProcedureDescriptor descriptor = (ProcedureDescriptor)PROCEDURES.get(cls);
-
- if(descriptor == null){
-
- throw new IllegalStateException("no procedure registred for " + cls.getName() );
+ private static Method findMethod(Class cls, JavaMethod jmethod){
- }
-
- return Proxy.newProxyInstance(cls.getClassLoader(),
- new Class[]{cls},
- new Invocation(connection, descriptor)
- );
+ Method methods[] = cls.getDeclaredMethods();
+ for(int i=0; i< methods.length; i++ ){
+
+ if(methods[i].getName().equals(jmethod.getName()) ){
+
+ JavaParameter jparams[] = jmethod.getParameters();
+ Class params[] = methods[i].getParameterTypes();
+
+ if( params.length == jparams.length ){
+
+ for( int j = 0; j < params.length; j++ ){
+
+ if(!params[j].getName().equals(jparams[j].getType().getValue()) ){
+ continue;
+ }
+
+ }
+
+ return methods[i];
+ }
+
+ }
+ }
+
+ throw new IllegalStateException("metadata not found for " + jmethod);
+ }
+
+ private static ResultSetHandler findHandler(Method method,
+ JavaMethod jmethod){
+
- }
- static class Invocation implements InvocationHandler{
-
- Connection connection;
- ProcedureDescriptor descriptor;
-
- Invocation(Connection connection,ProcedureDescriptor descriptor){
- this.connection = connection;
- this.descriptor = descriptor;
- }
+ ResultSetHandler handler = null;
+
+ String name = null;
- private Object[] prepareArgs(Object[] args){
- int len = descriptor.indexMap.length;
- Object pargs[] = new Object[ len ];
- for(int i = 0; i < len; i++ ){
- pargs[i] = args[ descriptor.indexMap[i] ];
- }
- return pargs;
+ DocletTag tag = jmethod.getTagByName("handler");
+ if(tag != null ){
+ name = tag.getValue();
+ if(name != null){
+ return (ResultSetHandler)PREDEFINED_HANDLERS.get(name);
}
- //TODO: some way to handle SQLException
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if(!descriptor.update){
- return DbUtils.executeQuery( connection,
- descriptor.jdbcSQL,
- prepareArgs(args),
- descriptor.handler
- );
- }else{
- int updateCount = DbUtils.executeUpdate( connection,
- descriptor.jdbcSQL,
- prepareArgs(args)
- );
-
- if(method.getReturnType() == Void.TYPE ){
- return null;
- }else {
- return new Integer(updateCount);
+ }
+
+ if( name == null && method.getReturnType().isPrimitive() ){
+ return SCALAR_HANDLER;
+ }
+
+ if(name != null){
+ try{
+ handler = (ResultSetHandler)method.getDeclaringClass().
+ getClassLoader().loadClass(name).newInstance();
+ }catch(Exception e){
+ throw new IllegalStateException( e.getMessage() + ":" + handler + " " + name +
+ " not found in " + method );
+ }
+ }
+
+ return handler;
+ }
+
+ private static Map buildProcedures(Class cls){
+
+ String res = cls.getName().replace('.','/') + ".java";
+ InputStream is = cls.getClassLoader().getResourceAsStream(res);
+ Map desctiptors = new HashMap();
+
+ if( is == null ){
+ throw new IllegalStateException( "resource " + res + " not found" );
+ }
+
+ JavaDocBuilder builder = new JavaDocBuilder();
+ builder.addSource( new InputStreamReader(is) );
+ JavaClass jclass = builder.getClassByName(cls.getName());
+ JavaMethod [] jmethods = jclass.getMethods();
+
+ for( int i = 0; i< jmethods.length; i++ ){
+
+ DocletTag tag = jmethods[i].getTagByName("sql");
+ if(tag == null){
+ throw new IllegalStateException("no @sql attribute in " + res + " " + jmethods[i]);
}
- }
- }
-
- }
+ String sql = tag.getValue();
+ Method method = findMethod(cls, jmethods[i] );
+ boolean update = jmethods[i].getTagByName("update") != null;
+ ResultSetHandler handler = null;
+ if( !update ){
+ handler = findHandler(method,jmethods[i] );
+ }
+
+ desctiptors.put( method,
+ compile( method, sql, handler, update ));
+ }
+
+ return desctiptors;
+
+ }
+ //TODO:
+ private static Object convert( Class convertTo, Object obj ){
+ return obj;
+ }
+
+ public static Object getInstance(Class cls, Connection connection){
+
+ Map descriptors = (Map)PROCEDURES.get(cls);
+
+ if(descriptors == null){
+
+ descriptors = buildProcedures(cls);
+ PROCEDURES.put(cls, descriptors);
+
+ }
+
+ return Proxy.newProxyInstance(cls.getClassLoader(),
+ new Class[]{cls},
+ new Invocation(connection, descriptors)
+ );
+
+ }
+
+ static class Invocation implements InvocationHandler{
+
+ Connection connection;
+ Map descriptors;
+
+ Invocation(Connection connection,Map descriptors){
+ this.connection = connection;
+ this.descriptors = descriptors;
+ }
+
+ private Object[] prepareArgs(ProcedureDescriptor descriptor, Object[] args){
+ int len = descriptor.indexMap.length;
+ Object pargs[] = new Object[ len ];
+ for(int i = 0; i < len; i++ ){
+ pargs[i] = args[ descriptor.indexMap[i] ];
+ }
+ return pargs;
+ }
+ //TODO: some way to handle SQLException
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+
+ if(method.getDeclaringClass() == Object.class ){
+ return null;
+ }
+
+ ProcedureDescriptor descriptor = (ProcedureDescriptor)descriptors.get(method);
+
+ if(descriptor == null){
+
+ throw new IllegalStateException("no descriptor found for " + method);
+
+ }
+
+ if(!descriptor.update){
+ return convert( method.getReturnType(), DbUtils.executeQuery( connection,
+ descriptor.jdbcSQL,
+ prepareArgs(descriptor,args),
+ descriptor.handler
+ ));
+ }else{
+ int updateCount = DbUtils.executeUpdate( connection,
+ descriptor.jdbcSQL,
+ prepareArgs(descriptor,args)
+ );
+
+ if(method.getReturnType() == Void.TYPE ){
+ return null;
+ }else {
+ return new Integer(updateCount);
+ }
+ }
+ }
+
+
+
+ }
}
1.1 jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ResultSetHandler.java
Index: ResultSetHandler.java
===================================================================
package org.apache.commons.dbutils;
/**
*
* @author baliuka
*/
public interface ResultSetHandler{
public Object handle(java.sql.ResultSet rs)throws java.sql.SQLException;
}
1.1 jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ScalarHandler.java
Index: ScalarHandler.java
===================================================================
package org.apache.commons.dbutils;
import java.sql.*;
/**
*
* @author user
*/
public class ScalarHandler implements ResultSetHandler {
/** Creates a new instance of ScalarHandler */
public ScalarHandler() {
}
public Object handle(ResultSet rs)throws SQLException{
if (rs.next()) {
Object result = rs.getObject(1);
return result;
}
throw new SQLException();
}
}
1.1 jakarta-commons-sandbox/dbutils/src/test/connection.properties
Index: connection.properties
===================================================================
driver=org.postgresql.Driver
url=jdbc:postgresql:test
user=test
password=test
1.1 jakarta-commons-sandbox/dbutils/src/test/org/apache/commons/dbutils/Demo.java
Index: Demo.java
===================================================================
package org.apache.commons.dbutils;
/**
*
* @author baliuka
*/
public interface Demo {
/**
*@sql CREATE TABLE TBL (ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(128))
*@update
*/
void create();
/**
*@sql DROP TABLE TBL
*@update
*/
void drop();
/**
*@sql SELECT COUNT(1) > 0 FROM TBL WHERE ID=$1
*/
public boolean exists(int id);
/**
*@sql INSERT INTO TBL (ID) VALUES($1)
*@update
*/
public int addId(int id);
/**
*@sql DELETE FROM TBL
*@update
*/
public void clear();
}
1.1 jakarta-commons-sandbox/dbutils/src/test/org/apache/commons/dbutils/ProcedureUtilsTest.java
Index: ProcedureUtilsTest.java
===================================================================
package org.apache.commons.dbutils;
import java.util.*;
import java.lang.reflect.*;
import java.sql.*;
import java.io.*;
import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.model.*;
import junit.framework.*;
/**
*
* @author baliuka
*/
public class ProcedureUtilsTest extends TestCase {
static java.sql.Connection connection;
public ProcedureUtilsTest(java.lang.String testName) {
super(testName);
}
public static void main(java.lang.String[] args) throws Exception{
junit.textui.TestRunner.run(suite());
}
public static Test suite() throws Exception{
java.util.Properties props = new java.util.Properties();
props.load(ProcedureUtilsTest.class.getClassLoader().getResourceAsStream("connection.properties"));
Class.forName(props.getProperty("driver").trim());
connection = java.sql.DriverManager.getConnection(props.getProperty("url"), props);
assertTrue(connection != null);
TestSuite suite = new TestSuite(ProcedureUtilsTest.class);
return suite;
}
public void testCreate() {
Demo demo = (Demo)ProcedureUtils.getInstance(Demo.class ,connection);
try{
demo.drop();
}catch(Exception e){e.printStackTrace();}
demo.create();
}
public void testGetInstance() {
Demo demo = (Demo)ProcedureUtils.getInstance(Demo.class ,connection);
demo.clear();
assertTrue( !demo.exists(1) );
assertTrue( demo.addId(1) == 1 );
assertTrue( demo.exists(1) );
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org