baliuka 2003/03/09 09:14:19 Modified: dbutils/src/java/org/apache/commons/dbutils DbUtils.java ProcedureUtils.java ResultSetHandler.java ScalarHandler.java dbutils/src/test/org/apache/commons/dbutils Demo.java ProcedureUtilsTest.java Added: dbutils/src/java/org/apache/commons/dbutils DbException.java Log: Added more tests, changed handler interface Revision Changes Path 1.12 +5 -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.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- DbUtils.java 8 Mar 2003 20:35:05 -0000 1.11 +++ DbUtils.java 9 Mar 2003 17:14:18 -0000 1.12 @@ -67,7 +67,7 @@ public static abstract class ListAdapter extends ArrayList implements ResultSetHandler{ - final public Object handle(ResultSet rs)throws SQLException{ + final public Object handle(ResultSet rs,Object[] params)throws SQLException{ while(rs.next()){ add(fetch(rs)); @@ -97,7 +97,7 @@ do{ rs = stmt.getResultSet(); - rsh.handle(rs); + rsh.handle(rs,vals); }while(stmt.getMoreResults()); @@ -141,7 +141,7 @@ rethrow( sqle, query, vals); } - return rsh.handle(rs); + return rsh.handle(rs,vals); } finally { closeQuietly(rs); @@ -253,7 +253,7 @@ return ((Number) executeQuery(connection, query, vals, new ResultSetHandler(){ - public Object handle(ResultSet rs)throws SQLException{ + public Object handle(ResultSet rs, Object[] params)throws SQLException{ ResultSetMetaData rsmd = rs.getMetaData(); if(rsmd.getColumnCount() > 1 ){ throwMultipleResults(query, vals); @@ -286,7 +286,7 @@ return ((Object[]) executeQuery(connection, query, vals, new ResultSetHandler(){ - public Object handle(ResultSet rs)throws SQLException{ + public Object handle(ResultSet rs,Object[] params)throws SQLException{ if (rs.next()) { return resultSetToArray(rs); 1.3 +158 -164 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.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ProcedureUtils.java 8 Mar 2003 20:35:05 -0000 1.2 +++ ProcedureUtils.java 9 Mar 2003 17:14:19 -0000 1.3 @@ -66,62 +66,6 @@ import com.thoughtworks.qdox.model.*; /** - * sample: - * class DAO { - * - * static interface Procedure{ - * int execute(int p1); - * } - * - * static interface Procedure2{ - * 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" - * ); - * - * salarProc(Procedure.class, - * "SELECT SUM(VALUE) - $2 FROM MY_TABLE WHERE VALUE > $1" - * - * ); - * } - * - * static Procedure getProcedure(){ - * return (Procedure)ProcedureUtils.getInstance(Procedure.class, - * currentConnection()); - * } - * - * static Procedure getProcedure2(){ - * return (Procedure2)ProcedureUtils.getInstance(Procedure2.class, - * 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 COUNT(*) FROM MY_TABLE WHERE VALUE < $1 and VALUE >= $2 - * int getCount(int p1, int p2); - * } - * * * @author baliuka */ @@ -130,6 +74,8 @@ private static final Map PROCEDURES = new HashMap(); private static final Map PREDEFINED_HANDLERS = new HashMap(); private static final ResultSetHandler SCALAR_HANDLER = new ScalarHandler(); + private static final String UPDATE_TAG = "update"; + private static final String QUERY_TAG = "query"; static class ProcedureDescriptor{ @@ -149,7 +95,7 @@ } - private static ProcedureDescriptor compile(Method proc, String sqlStr, + static ProcedureDescriptor compile(Method proc, String sqlStr, ResultSetHandler handler,boolean update){ java.util.ArrayList indexes = new java.util.ArrayList(); @@ -180,8 +126,8 @@ if( i != sql.length - 1 ){ continue; }else { - i++; - } + i++; + } } if(arg){ @@ -189,8 +135,8 @@ sb.append('?'); digit.delete(0, digit.length() ); } - if( i < sql.length ){ - sb.append(sql[i]); + if( i < sql.length ){ + sb.append(sql[i]); } escape = false; arg = false; @@ -214,12 +160,12 @@ } 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); + int param = ((Number)i.next()).intValue(); + if(param == 0 || param > proc.getParameterTypes().length ){ + throw new IllegalArgumentException( "extra prameter " + + i + " in " + proc); } - + } ProcedureDescriptor descriptor = new ProcedureDescriptor(); @@ -243,31 +189,8 @@ return descriptor; } - - 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(Method proc, String sql){ - register( proc, sql, null, false); - } - - - 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); - - } - - private static Method findMethod(Class cls, JavaMethod jmethod){ + + static Method findMethod(Class cls, JavaMethod jmethod){ Method methods[] = cls.getDeclaredMethods(); for(int i=0; i< methods.length; i++ ){ @@ -296,40 +219,86 @@ throw new IllegalStateException("metadata not found for " + jmethod); } - private static ResultSetHandler findHandler(Method method, - JavaMethod jmethod){ - - - ResultSetHandler handler = null; - - String name = null; - - DocletTag tag = jmethod.getTagByName("handler"); - if(tag != null ){ - name = tag.getValue(); - if(name != null){ - return (ResultSetHandler)PREDEFINED_HANDLERS.get(name); - } - } - - 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 ); - } + static ResultSetHandler findHandler(Method method, JavaMethod jmethod){ + + + ResultSetHandler handler = null; + + String name = null; + + DocletTag tag = jmethod.getTagByName("handler"); + + if(tag != null ){ + name = tag.getValue(); + + name = (name == null || name.trim().length() == 0 ? null : name.trim() ); + } + + handler = (ResultSetHandler)PREDEFINED_HANDLERS.get(name); + + if(name != null && handler != null ){ + + return handler; + } + + + if( name == null && method.getReturnType().isPrimitive() ){ + + return SCALAR_HANDLER; + } + + + if(name != null){ + String imports[] = jmethod.getParentClass(). + getParentSource().getImports(); + String names[] = { + name, + jmethod.getParentClass().getPackage() + "." + name, + "org.apache.commons.dbutils." + name + }; + + + ClassLoader loader = method.getDeclaringClass().getClassLoader(); + + try{ + + for(int i = 0; i < names.length; i++){ + + try{ + + return (ResultSetHandler)loader.loadClass(names[i]).newInstance(); + + }catch(ClassNotFoundException cnfe){ + + } + + } + for(int i = 0; i < imports.length; i++){ + + try{ + if(imports[i].endsWith( name )){ + return (ResultSetHandler)loader.loadClass(imports[i]).newInstance(); + }else if(imports[i].endsWith("*")){ + + return (ResultSetHandler)loader.loadClass( + imports[i].substring(0,imports[i].length() - 1 ) + name).newInstance(); + } + + }catch(ClassNotFoundException cnfe){ + + } + } + + }catch(Exception e){ + throw new IllegalStateException( e.getMessage() + ":" + name + + " not found for " + method ); + } + } + + throw new IllegalStateException( "Handler not found for " + method ); } - return handler; - } - - private static Map buildProcedures(Class cls){ + static Map buildProcedures(Class cls){ String res = cls.getName().replace('.','/') + ".java"; InputStream is = cls.getClassLoader().getResourceAsStream(res); @@ -346,38 +315,43 @@ 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]); + DocletTag queryTag = jmethods[i].getTagByName(QUERY_TAG); + DocletTag updateTag = jmethods[i].getTagByName(UPDATE_TAG); + + if(queryTag == null && updateTag == null ){ + throw new IllegalStateException("no [dbutils] attributes (" + QUERY_TAG + + "," + UPDATE_TAG + ") in " + res + " " + jmethods[i]); } - String sql = tag.getValue(); + String sql = updateTag == null ? queryTag.getValue() : updateTag.getValue(); Method method = findMethod(cls, jmethods[i] ); - boolean update = jmethods[i].getTagByName("update") != null; + boolean update = updateTag != null; ResultSetHandler handler = null; if( !update ){ - handler = findHandler(method,jmethods[i] ); + handler = findHandler(method,jmethods[i] ); } - - desctiptors.put( method, - compile( method, sql, handler, update )); + + desctiptors.put( method, + compile( method, sql, handler, update )); } - return desctiptors; + return desctiptors; } - //TODO: - private static Object convert( Class convertTo, Object obj ){ - return obj; + //TODO: ConvertUtils + static Object convert( Class to, Object from ){ + + return from; } + public static Object getInstance(Class cls, Connection connection){ Map descriptors = (Map)PROCEDURES.get(cls); if(descriptors == null){ - descriptors = buildProcedures(cls); - PROCEDURES.put(cls, descriptors); + descriptors = buildProcedures(cls); + PROCEDURES.put(cls, descriptors); } @@ -406,38 +380,58 @@ } 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){ + try{ - throw new IllegalStateException("no descriptor found for " + method); + if(method.getDeclaringClass() == Object.class ){ + + return method.invoke(connection,args); + } - } - - 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) - ); + ProcedureDescriptor descriptor = (ProcedureDescriptor)descriptors.get(method); - if(method.getReturnType() == Void.TYPE ){ - return null; - }else { - return new Integer(updateCount); + 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); + } + } + }catch(RuntimeException re){ + + throw re; + + }catch(Exception e){ + + Class exeptions[] = method.getExceptionTypes(); + for( int i = 0; i< exeptions.length; i++){ + + if(exeptions[i] == e.getClass() ){ + throw e; + } + } + + throw new DbException(e, method.toString() ); + } } 1.2 +1 -1 jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ResultSetHandler.java Index: ResultSetHandler.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ResultSetHandler.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ResultSetHandler.java 8 Mar 2003 20:35:05 -0000 1.1 +++ ResultSetHandler.java 9 Mar 2003 17:14:19 -0000 1.2 @@ -7,6 +7,6 @@ */ public interface ResultSetHandler{ - public Object handle(java.sql.ResultSet rs)throws java.sql.SQLException; + public Object handle(java.sql.ResultSet rs,Object params[])throws java.sql.SQLException; } 1.2 +2 -1 jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ScalarHandler.java Index: ScalarHandler.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/ScalarHandler.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ScalarHandler.java 8 Mar 2003 20:35:05 -0000 1.1 +++ ScalarHandler.java 9 Mar 2003 17:14:19 -0000 1.2 @@ -11,7 +11,7 @@ public ScalarHandler() { } - public Object handle(ResultSet rs)throws SQLException{ + public Object handle(ResultSet rs,Object[] params)throws SQLException{ if (rs.next()) { Object result = rs.getObject(1); @@ -20,4 +20,5 @@ throw new SQLException(); } + } 1.1 jakarta-commons-sandbox/dbutils/src/java/org/apache/commons/dbutils/DbException.java Index: DbException.java =================================================================== package org.apache.commons.dbutils; /** * * @author baliuka */ public class DbException extends java.lang.RuntimeException { private Throwable cause; /** * Creates a new instance of <code>DbException</code> without detail message. */ public DbException(Throwable cause) { this.cause = cause; } /** * Constructs an instance of <code>DbException</code> with the specified detail message. * @param msg the detail message. */ public DbException(Throwable cause,String msg) { super(msg); this.cause = cause; } /** * Constructs an instance of <code>DbException</code> with the specified detail message. * @param msg the detail message. */ public DbException(String msg) { super(msg); } public Throwable getCause(){ return cause; } } 1.2 +26 -13 jakarta-commons-sandbox/dbutils/src/test/org/apache/commons/dbutils/Demo.java Index: Demo.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/dbutils/src/test/org/apache/commons/dbutils/Demo.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Demo.java 8 Mar 2003 20:35:05 -0000 1.1 +++ Demo.java 9 Mar 2003 17:14:19 -0000 1.2 @@ -2,43 +2,56 @@ package org.apache.commons.dbutils; /** - * + * this file is used for metadata and must be in classpath at runtime * @author baliuka */ public interface Demo { /** - [EMAIL PROTECTED] CREATE TABLE TBL (ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(128)) - [EMAIL PROTECTED] + [EMAIL PROTECTED] CREATE TABLE TBL (ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(128)) */ void create(); /** - [EMAIL PROTECTED] DROP TABLE TBL - [EMAIL PROTECTED] + [EMAIL PROTECTED] DROP TABLE TBL */ void drop(); /** - [EMAIL PROTECTED] SELECT COUNT(1) > 0 FROM TBL WHERE ID=$1 + [EMAIL PROTECTED] SELECT COUNT(1) > 0 FROM TBL WHERE ID=$1 */ public boolean exists(int id); /** - [EMAIL PROTECTED] INSERT INTO TBL (ID) VALUES($1) - [EMAIL PROTECTED] - */ - public int addId(int id); + [EMAIL PROTECTED] INSERT INTO TBL (ID, NAME) VALUES($1,$2) + */ + public int add(int id,String name); /** - [EMAIL PROTECTED] DELETE FROM TBL - [EMAIL PROTECTED] - */ + [EMAIL PROTECTED] DELETE FROM TBL + */ public void clear(); + /** + [EMAIL PROTECTED] SELECT ID, NAME FROM TBL + [EMAIL PROTECTED] DemoHandler + */ + public int print(); + /** + [EMAIL PROTECTED] SELECT SELECT As FROM TBL + * + */ + public void error()throws java.sql.SQLException; + + /** + [EMAIL PROTECTED] SELECT SELECT As FROM TBL + * + */ + + public void undeclaredError(); } 1.2 +43 -4 jakarta-commons-sandbox/dbutils/src/test/org/apache/commons/dbutils/ProcedureUtilsTest.java Index: ProcedureUtilsTest.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/dbutils/src/test/org/apache/commons/dbutils/ProcedureUtilsTest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ProcedureUtilsTest.java 8 Mar 2003 20:35:05 -0000 1.1 +++ ProcedureUtilsTest.java 9 Mar 2003 17:14:19 -0000 1.2 @@ -41,24 +41,63 @@ return suite; } + private Demo getDemo(){ + return(Demo)ProcedureUtils.getInstance(Demo.class ,connection); + } + public void testCreate() { - Demo demo = (Demo)ProcedureUtils.getInstance(Demo.class ,connection); + Demo demo = getDemo(); try{ demo.drop(); }catch(Exception e){e.printStackTrace();} demo.create(); } + public void testGetInstance() { - Demo demo = (Demo)ProcedureUtils.getInstance(Demo.class ,connection); + Demo demo = getDemo(); demo.clear(); assertTrue( !demo.exists(1) ); - assertTrue( demo.addId(1) == 1 ); + assertTrue( demo.add(1,"test") == 1 ); assertTrue( demo.exists(1) ); - + for( int i = 0; i< 10;i++){ + demo.add(i + 2,"test" + i); + } + demo.print(); + demo.clear(); + } + public void testSQLException() { + + try{ + + getDemo().error(); + fail("must throw SQException"); + + }catch(SQLException ok){ + + }catch(Exception e){ + fail(e.getMessage()); + } + + } + + public void testUndeclaredSQLException() { + + try{ + + getDemo().undeclaredError(); + fail("must throw DbException"); + + }catch(DbException ok){ + + }catch(Exception e){ + fail(e.getMessage()); + } + + } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]