You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by cb...@apache.org on 2008/08/08 01:21:58 UTC

svn commit: r683745 [18/22] - in /ibatis/trunk/java/ibatis-3: ./ ibatis-3-compat/ ibatis-3-compat/src/ ibatis-3-compat/src/main/ ibatis-3-compat/src/main/java/ ibatis-3-compat/src/main/java/com/ ibatis-3-compat/src/main/java/com/ibatis/ ibatis-3-compat...

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMapping.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMapping.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMapping.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMapping.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,111 @@
+package org.apache.ibatis.mapping;
+
+import org.apache.ibatis.type.*;
+
+import java.util.*;
+
+public class ResultMapping {
+
+  private String property;
+  private String column;
+  private Class javaType;
+  private JdbcType jdbcType;
+  private TypeHandler typeHandler;
+  private String nestedResultMapId;
+  private String nestedQueryId;
+  private List<ResultFlag> flags;
+  private List<ResultMapping> composites;
+
+  private ResultMapping() {
+  }
+
+  public static class Builder {
+    private ResultMapping resultMapping = new ResultMapping();
+
+    public Builder(String property, String column, TypeHandler typeHandler) {
+      resultMapping.property = property;
+      resultMapping.column = column;
+      resultMapping.typeHandler = typeHandler;
+      resultMapping.flags = new ArrayList<ResultFlag>();
+      resultMapping.composites = new ArrayList<ResultMapping>();
+    }
+
+    public Builder javaType(Class javaType) {
+      resultMapping.javaType = javaType;
+      return this;
+    }
+
+    public Builder jdbcType(JdbcType jdbcType) {
+      resultMapping.jdbcType = jdbcType;
+      return this;
+    }
+
+    public Builder nestedResultMapId(String nestedResultMapId) {
+      resultMapping.nestedResultMapId = nestedResultMapId;
+      return this;
+    }
+
+    public Builder nestedQueryId(String nestedQueryId) {
+      resultMapping.nestedQueryId = nestedQueryId;
+      return this;
+    }
+
+    public Builder flags(List<ResultFlag> flags) {
+      resultMapping.flags = flags;
+      return this;
+    }
+
+    public ResultMapping build() {
+      //lock down collections
+      resultMapping.flags = Collections.unmodifiableList(resultMapping.flags);
+      resultMapping.composites = Collections.unmodifiableList(resultMapping.composites);
+      return resultMapping;
+    }
+
+    public Builder composites(List<ResultMapping> composites) {
+      resultMapping.composites = composites;
+      return this;
+    }
+  }
+
+  public String getProperty() {
+    return property;
+  }
+
+  public String getColumn() {
+    return column;
+  }
+
+  public Class getJavaType() {
+    return javaType;
+  }
+
+  public JdbcType getJdbcType() {
+    return jdbcType;
+  }
+
+  public TypeHandler getTypeHandler() {
+    return typeHandler;
+  }
+
+  public String getNestedResultMapId() {
+    return nestedResultMapId;
+  }
+
+  public String getNestedQueryId() {
+    return nestedQueryId;
+  }
+
+  public List<ResultFlag> getFlags() {
+    return flags;
+  }
+
+  public List<ResultMapping> getComposites() {
+    return composites;
+  }
+
+  public boolean isCompositeResult() {
+    return this.composites != null && !this.composites.isEmpty();
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultSetType.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultSetType.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultSetType.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultSetType.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,19 @@
+package org.apache.ibatis.mapping;
+
+import java.sql.ResultSet;
+
+public enum ResultSetType {
+  FORWARD_ONLY(ResultSet.TYPE_FORWARD_ONLY),
+  SCROLL_INSENSITIVE(ResultSet.TYPE_SCROLL_INSENSITIVE),
+  SCROLL_SENSITIVE(ResultSet.TYPE_SCROLL_SENSITIVE);
+
+  private int value;
+
+  ResultSetType(int value) {
+    this.value = value;
+  }
+
+  public int getValue() {
+    return value;
+  }
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/SqlSource.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/SqlSource.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/SqlSource.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/SqlSource.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,11 @@
+package org.apache.ibatis.mapping;
+
+import java.util.List;
+
+public interface SqlSource {
+
+  String getSql(Object parameterObject);
+
+  List<ParameterMapping> getParameterMappings(Object parameterObject);
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/StatementType.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/StatementType.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/StatementType.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/StatementType.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,5 @@
+package org.apache.ibatis.mapping;
+
+public enum StatementType {
+  STATEMENT, PREPARED, CALLABLE
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/ScriptRunner.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/ScriptRunner.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/ScriptRunner.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/ScriptRunner.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,242 @@
+package org.apache.ibatis.migration;
+
+
+import javax.sql.DataSource;
+import java.io.*;
+import java.sql.*;
+
+/**
+ * Utility to run database scripts
+ */
+public class ScriptRunner {
+
+  private static final String DEFAULT_DELIMITER = ";";
+
+  private DataSource dataSource;
+  private Connection connection;
+  private String driver;
+  private String url;
+  private String username;
+  private String password;
+
+  private boolean stopOnError;
+  private boolean autoCommit;
+
+  private PrintWriter logWriter = new PrintWriter(System.out);
+  private PrintWriter errorLogWriter = new PrintWriter(System.err);
+
+  private String delimiter = DEFAULT_DELIMITER;
+  private boolean fullLineDelimiter = false;
+
+  public ScriptRunner(DataSource dataSource, boolean autoCommit, boolean stopOnError) {
+    this.dataSource = dataSource;
+    this.autoCommit = autoCommit;
+    this.stopOnError = stopOnError;
+  }
+
+  public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError) {
+    this.connection = connection;
+    this.autoCommit = autoCommit;
+    this.stopOnError = stopOnError;
+  }
+
+  public ScriptRunner(String driver, String url, String username, String password, boolean autoCommit, boolean stopOnError) {
+    this.driver = driver;
+    this.url = url;
+    this.username = username;
+    this.password = password;
+    this.autoCommit = autoCommit;
+    this.stopOnError = stopOnError;
+  }
+
+  public void setDelimiter(String delimiter, boolean fullLineDelimiter) {
+    this.delimiter = delimiter;
+    this.fullLineDelimiter = fullLineDelimiter;
+  }
+
+  public void setLogWriter(PrintWriter logWriter) {
+    this.logWriter = logWriter;
+  }
+
+  public void setErrorLogWriter(PrintWriter errorLogWriter) {
+    this.errorLogWriter = errorLogWriter;
+  }
+
+  public void runScript(Reader reader) throws IOException, SQLException {
+    try {
+      if (dataSource != null) {
+        connection = dataSource.getConnection();
+        try {
+          configureAutoCommitAndRun(reader);
+        } finally {
+          connection.close();
+        }
+      } else if (connection != null) {
+        configureAutoCommitAndRun(reader);
+      } else {
+        Class driverType = Class.forName(driver);
+        DriverManager.registerDriver((Driver) driverType.newInstance());
+        connection = DriverManager.getConnection(url, username, password);
+        try {
+          configureAutoCommitAndRun(reader);
+        } finally {
+          try {
+            connection.close();
+          } finally {
+            connection = null;
+          }
+        }
+      }
+    } catch (IOException e) {
+      throw e;
+    } catch (SQLException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new RuntimeException("Error running script.  Cause: " + e, e);
+    }
+  }
+
+  private void configureAutoCommitAndRun(Reader reader) throws SQLException, IOException {
+    boolean originalAutoCommit = connection.getAutoCommit();
+    try {
+      if (originalAutoCommit != this.autoCommit) {
+        connection.setAutoCommit(this.autoCommit);
+      }
+      runScriptWithConnection(connection, reader);
+    } finally {
+      connection.setAutoCommit(originalAutoCommit);
+    }
+  }
+
+  /**
+   * Runs an SQL script (read in using the Reader parameter) using the connection passed in
+   *
+   * @param conn   - the connection to use for the script
+   * @param reader - the source of the script
+   * @throws java.sql.SQLException if any SQL errors occur
+   * @throws java.io.IOException   if there is an error reading from the Reader
+   */
+  private void runScriptWithConnection(Connection conn, Reader reader)
+      throws IOException, SQLException {
+    StringBuffer command = null;
+    try {
+      LineNumberReader lineReader = new LineNumberReader(reader);
+      String line;
+      while ((line = lineReader.readLine()) != null) {
+        if (command == null) {
+          command = new StringBuffer();
+        }
+        String trimmedLine = line.trim();
+        if (trimmedLine.startsWith("--")) {
+          println(trimmedLine);
+        } else if (trimmedLine.length() < 1 || trimmedLine.startsWith("//")) {
+          //Do nothing
+        } else if (trimmedLine.length() < 1 || trimmedLine.startsWith("--")) {
+          //Do nothing
+        } else if (!fullLineDelimiter && trimmedLine.endsWith(getDelimiter())
+            || fullLineDelimiter && trimmedLine.equals(getDelimiter())) {
+          command.append(line.substring(0, line.lastIndexOf(getDelimiter())));
+          command.append(" ");
+          Statement statement = conn.createStatement();
+
+          println(command);
+
+          boolean hasResults = false;
+          if (stopOnError) {
+            hasResults = statement.execute(command.toString());
+          } else {
+            try {
+              hasResults = statement.execute(command.toString());
+            } catch (SQLException e) {
+              e.fillInStackTrace();
+              printlnError("Error executing: " + command);
+              printlnError(e);
+            }
+          }
+
+          if (autoCommit && !conn.getAutoCommit()) {
+            conn.commit();
+          }
+
+          ResultSet rs = statement.getResultSet();
+          if (hasResults && rs != null) {
+            ResultSetMetaData md = rs.getMetaData();
+            int cols = md.getColumnCount();
+            for (int i = 0; i < cols; i++) {
+              String name = md.getColumnLabel(i + 1);
+              print(name + "\t");
+            }
+            println("");
+            while (rs.next()) {
+              for (int i = 0; i < cols; i++) {
+                String value = rs.getString(i + 1);
+                print(value + "\t");
+              }
+              println("");
+            }
+          }
+
+          command = null;
+          try {
+            statement.close();
+          } catch (Exception e) {
+            // Ignore to workaround a bug in Jakarta DBCP
+          }
+          Thread.yield();
+        } else {
+          command.append(line);
+          command.append(" ");
+        }
+      }
+      if (!autoCommit) {
+        conn.commit();
+      }
+    } catch (SQLException e) {
+      e.fillInStackTrace();
+      printlnError("Error executing: " + command);
+      printlnError(e);
+      throw e;
+    } catch (IOException e) {
+      e.fillInStackTrace();
+      printlnError("Error executing: " + command);
+      printlnError(e);
+      throw e;
+    } finally {
+      conn.rollback();
+      flush();
+    }
+  }
+
+  private String getDelimiter() {
+    return delimiter;
+  }
+
+  private void print(Object o) {
+    if (logWriter != null) {
+      System.out.print(o);
+    }
+  }
+
+  private void println(Object o) {
+    if (logWriter != null) {
+      logWriter.println(o);
+    }
+  }
+
+  private void printlnError(Object o) {
+    if (errorLogWriter != null) {
+      errorLogWriter.println(o);
+    }
+  }
+
+  private void flush() {
+    if (logWriter != null) {
+      logWriter.flush();
+    }
+    if (errorLogWriter != null) {
+      errorLogWriter.flush();
+    }
+  }
+
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Interceptor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Interceptor.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Interceptor.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Interceptor.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,9 @@
+package org.apache.ibatis.plugin;
+
+public interface Interceptor {
+
+  Object intercept(Invocation invocation) throws Throwable;
+
+  Object plugin(Object target);
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/InterceptorChain.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/InterceptorChain.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/InterceptorChain.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/InterceptorChain.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,20 @@
+package org.apache.ibatis.plugin;
+
+import java.util.*;
+
+public class InterceptorChain {
+
+  private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
+
+  public Object pluginAll(Object target) {
+    for (Interceptor interceptor : interceptors) {
+      target = interceptor.plugin(target);
+    }
+    return target;
+  }
+
+  public void addInterceptor(Interceptor interceptor) {
+    interceptors.add(interceptor);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Intercepts.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Intercepts.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Intercepts.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Intercepts.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,10 @@
+package org.apache.ibatis.plugin;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Intercepts {
+  Signature[] value();
+}
+

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Invocation.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Invocation.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Invocation.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Invocation.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,33 @@
+package org.apache.ibatis.plugin;
+
+import java.lang.reflect.*;
+
+public class Invocation {
+
+  private Object target;
+  private Method method;
+  private Object[] args;
+
+  public Invocation(Object target, Method method, Object[] args) {
+    this.target = target;
+    this.method = method;
+    this.args = args;
+  }
+
+  public Object getTarget() {
+    return target;
+  }
+
+  public Method getMethod() {
+    return method;
+  }
+
+  public Object[] getArgs() {
+    return args;
+  }
+
+  public Object proceed() throws InvocationTargetException, IllegalAccessException {
+    return method.invoke(target, args);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Plugin.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Plugin.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Plugin.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Plugin.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,77 @@
+package org.apache.ibatis.plugin;
+
+import org.apache.ibatis.reflection.ExceptionUtil;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+public class Plugin implements InvocationHandler {
+
+  private Object target;
+  private Interceptor interceptor;
+  private Map<Class, Set<Method>> signatureMap;
+
+  private Plugin(Object target, Interceptor interceptor, Map<Class, Set<Method>> signatureMap) {
+    this.target = target;
+    this.interceptor = interceptor;
+    this.signatureMap = signatureMap;
+  }
+
+  public static Object wrap(Object target, Interceptor interceptor) {
+    Map<Class, Set<Method>> signatureMap = getSignatureMap(interceptor);
+    Class type = target.getClass();
+    Class[] interfaces = getAllInterfaces(type, signatureMap);
+    if (interfaces.length > 0) {
+      return Proxy.newProxyInstance(
+          type.getClassLoader(),
+          interfaces,
+          new Plugin(target, interceptor, signatureMap));
+    }
+    return target;
+  }
+
+  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+    try {
+      Set<Method> methods = signatureMap.get(method.getDeclaringClass());
+      if (methods != null && methods.contains(method)) {
+        return interceptor.intercept(new Invocation(target, method, args));
+      }
+      return method.invoke(target, args);
+    } catch (Exception e) {
+      throw ExceptionUtil.unwrapThrowable(e);
+    }
+  }
+
+  private static Map<Class, Set<Method>> getSignatureMap(Interceptor interceptor) {
+    Signature[] sigs = interceptor.getClass().getAnnotation(Intercepts.class).value();
+    Map<Class, Set<Method>> signatureMap = new HashMap<Class, Set<Method>>();
+    for (Signature sig : sigs) {
+      Set<Method> methods = signatureMap.get(sig.type());
+      if (methods == null) {
+        methods = new HashSet<Method>();
+        signatureMap.put(sig.type(), methods);
+      }
+      try {
+        Method method = sig.type().getMethod(sig.method(), sig.args());
+        methods.add(method);
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e);
+      }
+    }
+    return signatureMap;
+  }
+
+  private static Class[] getAllInterfaces(Class type, Map<Class, Set<Method>> signatureMap) {
+    Set<Class> interfaces = new HashSet<Class>();
+    while (type != null) {
+      for (Class c : type.getInterfaces()) {
+        if (signatureMap.containsKey(c)) {
+          interfaces.add(c);
+        }
+      }
+      type = type.getSuperclass();
+    }
+    return interfaces.toArray(new Class[interfaces.size()]);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Signature.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Signature.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Signature.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/plugin/Signature.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,13 @@
+package org.apache.ibatis.plugin;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Signature {
+  Class type();
+
+  String method();
+
+  Class[] args();
+}
\ No newline at end of file

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/DefaultObjectFactory.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/DefaultObjectFactory.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/DefaultObjectFactory.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/DefaultObjectFactory.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,57 @@
+package org.apache.ibatis.reflection;
+
+import java.lang.reflect.Constructor;
+import java.util.*;
+
+public class DefaultObjectFactory implements ObjectFactory {
+
+  public Object create(Class type) {
+    return create(type, null, null);
+  }
+
+  public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) {
+    Class classToCreate = resolveCollectionInterface(type);
+    return instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
+  }
+
+  public void setProperty(String name, String value) {
+    // no props for default
+  }
+
+  private Object instantiateClass(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) {
+    try {
+      Constructor constructor;
+      if (constructorArgTypes == null || constructorArgs == null) {
+        constructor = type.getDeclaredConstructor();
+        if (!constructor.isAccessible()) {
+          constructor.setAccessible(true);
+        }
+        return constructor.newInstance();
+      } else {
+        constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
+        if (!constructor.isAccessible()) {
+          constructor.setAccessible(true);
+        }
+        return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
+      }
+    } catch (Exception e) {
+      throw new RuntimeException("Error instantiating " + type + ". Cause: " + e, e);
+    }
+  }
+
+
+  private Class resolveCollectionInterface(Class type) {
+    Class classToCreate;
+    if (type == List.class || type == Collection.class) {
+      classToCreate = ArrayList.class;
+    } else if (type == Map.class) {
+      classToCreate = HashMap.class;
+    } else if (type == Set.class) {
+      classToCreate = HashSet.class;
+    } else {
+      classToCreate = type;
+    }
+    return classToCreate;
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ExceptionUtil.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ExceptionUtil.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ExceptionUtil.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ExceptionUtil.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,20 @@
+package org.apache.ibatis.reflection;
+
+import java.lang.reflect.*;
+
+public class ExceptionUtil {
+
+  public static Throwable unwrapThrowable(Throwable wrapped) {
+    Throwable unwrapped = wrapped;
+    while (true) {
+      if (unwrapped instanceof InvocationTargetException) {
+        unwrapped = ((InvocationTargetException) wrapped).getTargetException();
+      } else if (unwrapped instanceof UndeclaredThrowableException) {
+        unwrapped = ((UndeclaredThrowableException) wrapped).getUndeclaredThrowable();
+      } else {
+        return unwrapped;
+      }
+    }
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/GetFieldInvoker.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/GetFieldInvoker.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/GetFieldInvoker.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/GetFieldInvoker.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,19 @@
+package org.apache.ibatis.reflection;
+
+import java.lang.reflect.*;
+
+class GetFieldInvoker implements Invoker {
+  private Field field;
+
+  public GetFieldInvoker(Field field) {
+    this.field = field;
+  }
+
+  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
+    return field.get(target);
+  }
+
+  public Class getType() {
+    return field.getType();
+  }
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Invoker.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Invoker.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Invoker.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Invoker.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,9 @@
+package org.apache.ibatis.reflection;
+
+import java.lang.reflect.InvocationTargetException;
+
+interface Invoker {
+  Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
+
+  Class getType();
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaClass.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaClass.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaClass.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaClass.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,110 @@
+package org.apache.ibatis.reflection;
+
+public class MetaClass {
+
+  private Reflector reflector;
+
+  private MetaClass(Class type) {
+    this.reflector = Reflector.forClass(type);
+  }
+
+  public static MetaClass forClass(Class type) {
+    return new MetaClass(type);
+  }
+
+  public static boolean isClassCacheEnabled() {
+    return Reflector.isClassCacheEnabled();
+  }
+
+  public static void setClassCacheEnabled(boolean classCacheEnabled) {
+    Reflector.setClassCacheEnabled(classCacheEnabled);
+  }
+
+  public MetaClass metaClassForProperty(String name) {
+    Class propType = reflector.getGetterType(name);
+    return MetaClass.forClass(propType);
+  }
+
+  public String findProperty(String name) {
+    StringBuilder prop = buildProperty(name, new StringBuilder());
+    return prop.length() > 0 ? prop.toString() : null;
+  }
+
+  public String[] getGetterNames() {
+    return reflector.getGetablePropertyNames();
+  }
+
+  public String[] getSetterNames() {
+    return reflector.getSetablePropertyNames();
+  }
+
+  public Class getSetterType(String name) {
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaClass metaProp = metaClassForProperty(prop.getName());
+      return metaProp.getSetterType(prop.getChildren());
+    } else {
+      return reflector.getSetterType(prop.getName());
+    }
+  }
+
+  public Class getGetterType(String name) {
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaClass metaProp = metaClassForProperty(prop.getName());
+      return metaProp.getGetterType(prop.getChildren());
+    } else {
+      return reflector.getGetterType(prop.getName());
+    }
+  }
+
+  public boolean hasSetter(String name) {
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaClass metaProp = metaClassForProperty(prop.getName());
+      return metaProp.hasSetter(prop.getChildren());
+    } else {
+      return reflector.hasSetter(prop.getName());
+    }
+  }
+
+  public boolean hasGetter(String name) {
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaClass metaProp = metaClassForProperty(prop.getName());
+      return metaProp.hasGetter(prop.getChildren());
+    } else {
+      return reflector.hasGetter(prop.getName());
+    }
+  }
+
+  public Invoker getGetInvoker(String name) {
+    return reflector.getGetInvoker(name);
+  }
+
+  public Invoker getSetInvoker(String name) {
+    return reflector.getSetInvoker(name);
+  }
+
+  private StringBuilder buildProperty(String name, StringBuilder builder) {
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      String propertyName = reflector.findPropertyName(prop.getName());
+      if (propertyName != null) {
+        builder.append(propertyName);
+        builder.append(".");
+        MetaClass metaProp = metaClassForProperty(prop.getName());
+        metaProp.buildProperty(prop.getChildren(), builder);
+      }
+    } else {
+      String propertyName = reflector.findPropertyName(name);
+      if (propertyName != null) {
+        builder.append(propertyName);
+      }
+    }
+    return builder;
+  }
+
+}
+
+

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaObject.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaObject.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaObject.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MetaObject.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,293 @@
+package org.apache.ibatis.reflection;
+
+import java.util.*;
+
+public class MetaObject {
+
+  private Object object;
+  private MetaClass metaClass;
+  private ObjectFactory objectFactory;
+
+  private static final Object[] NO_ARGUMENTS = new Object[0];
+  private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
+
+  public static final MetaObject NULL_META_OBJECT = new MetaObject(NullObject.class, DEFAULT_OBJECT_FACTORY);
+
+  private MetaObject(Object object, ObjectFactory objectFactory) {
+    this.object = object;
+    this.metaClass = MetaClass.forClass(object.getClass());
+    this.objectFactory = objectFactory;
+  }
+
+  public static MetaObject forObject(Object object, ObjectFactory objectFactory) {
+    if (object == null) {
+      return NULL_META_OBJECT;
+    } else {
+      return new MetaObject(object, objectFactory);
+    }
+  }
+
+  public static MetaObject forObject(Object object) {
+    return forObject(object, DEFAULT_OBJECT_FACTORY);
+  }
+
+  public MetaObject metaObjectForProperty(String name) {
+    Object value = getValue(name);
+    return MetaObject.forObject(value);
+  }
+
+  public String findProperty(String propName) {
+    if (object instanceof Map) return propName;
+    return metaClass.findProperty(propName);
+  }
+
+  public String[] getGetterNames() {
+    if (object instanceof Map) return (String[]) ((Map) object).keySet().toArray(new String[((Map) object).size()]);
+    return metaClass.getGetterNames();
+  }
+
+  public String[] getSetterNames() {
+    if (object instanceof Map) return (String[]) ((Map) object).keySet().toArray(new String[((Map) object).size()]);
+    return metaClass.getSetterNames();
+  }
+
+  public Class getSetterType(String name) {
+    if (object instanceof Map)
+      return ((Map) object).get(name) == null ? Object.class : ((Map) object).get(name).getClass();
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
+      if (metaValue == MetaObject.NULL_META_OBJECT) {
+        return metaClass.getSetterType(name);
+      } else {
+        return metaValue.getSetterType(prop.getChildren());
+      }
+    } else {
+      return metaClass.getSetterType(name);
+    }
+  }
+
+  public Class getGetterType(String name) {
+    if (object instanceof Map)
+      return ((Map) object).get(name) == null ? Object.class : ((Map) object).get(name).getClass();
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
+      if (metaValue == MetaObject.NULL_META_OBJECT) {
+        return metaClass.getGetterType(name);
+      } else {
+        return metaValue.getGetterType(prop.getChildren());
+      }
+    } else {
+      return metaClass.getGetterType(name);
+    }
+  }
+
+  public boolean hasSetter(String name) {
+    if (object instanceof Map) return true;
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
+      if (metaValue == MetaObject.NULL_META_OBJECT) {
+        return metaClass.hasSetter(name);
+      } else {
+        return metaValue.hasSetter(prop.getChildren());
+      }
+    } else {
+      return metaClass.hasSetter(name);
+    }
+  }
+
+  public boolean hasGetter(String name) {
+    if (object instanceof Map) return true;
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
+      if (metaValue == MetaObject.NULL_META_OBJECT) {
+        return metaClass.hasGetter(name);
+      } else {
+        return metaValue.hasGetter(prop.getChildren());
+      }
+    } else {
+      return metaClass.hasGetter(name);
+    }
+  }
+
+  public Object getValue(String name) {
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
+      if (metaValue == MetaObject.NULL_META_OBJECT) {
+        return null;
+      } else {
+        return metaValue.getValue(prop.getChildren());
+      }
+    } else {
+      return getProperty(object, prop);
+    }
+  }
+
+  public void setValue(String name, Object value) {
+    PropertyTokenizer prop = new PropertyTokenizer(name);
+    if (prop.hasNext()) {
+      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
+      if (metaValue == MetaObject.NULL_META_OBJECT) {
+        if (value == null && prop.getChildren() != null) {
+          return; // don't instantiate child path if value is null
+        } else {
+          Class type = getSetterType(prop.getName());
+          try {
+            Object newObject = objectFactory.create(type);
+            metaValue = MetaObject.forObject(newObject);
+            setProperty(object, prop, newObject);
+          } catch (Exception e) {
+            throw new RuntimeException("Cannot set value of property '" + name + "' because '" + name + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
+          }
+        }
+      }
+      metaValue.setValue(prop.getChildren(), value);
+    } else {
+      setProperty(object, prop, value);
+    }
+
+  }
+
+  private Object getProperty(Object object, PropertyTokenizer prop) {
+    if (prop.getIndex() != null) {
+      return getIndexedProperty(object, prop);
+    } else {
+      return getBeanOrMapProperty(object, prop);
+    }
+  }
+
+  private Object getBeanOrMapProperty(Object object, PropertyTokenizer prop) {
+    if (object instanceof Map) {
+      return ((Map) object).get(prop.getName());
+    } else {
+      return getBeanProperty(object, prop);
+    }
+  }
+
+  private void setProperty(Object object, PropertyTokenizer prop, Object value) {
+    if (prop.getIndex() != null) {
+      setIndexedProperty(object, prop, value);
+    } else if (object instanceof Map) {
+      ((Map) object).put(prop.getName(), value);
+    } else {
+      setBeanProperty(object, prop, value);
+    }
+  }
+
+  private Object getBeanProperty(Object object, PropertyTokenizer prop) {
+    try {
+      Invoker method = metaClass.getGetInvoker(prop.getName());
+      try {
+        return method.invoke(object, NO_ARGUMENTS);
+      } catch (Throwable t) {
+        throw ExceptionUtil.unwrapThrowable(t);
+      }
+    } catch (RuntimeException e) {
+      throw e;
+    } catch (Throwable t) {
+      throw new RuntimeException("Could not get property '" + prop.getName() + "' from " + object + ".  Cause: " + t.toString(), t);
+    }
+  }
+
+  private void setBeanProperty(Object object, PropertyTokenizer prop, Object value) {
+    try {
+      Invoker method = metaClass.getSetInvoker(prop.getName());
+      Object[] params = {value};
+      try {
+        method.invoke(object, params);
+      } catch (Throwable t) {
+        throw ExceptionUtil.unwrapThrowable(t);
+      }
+    } catch (Throwable t) {
+      throw new RuntimeException("Could not set property '" + prop.getName() + "' for " + object + ".  Cause: " + t.toString(), t);
+    }
+  }
+
+  private Object getIndexedProperty(Object object, PropertyTokenizer prop) {
+    Object value;
+    try {
+      int i = Integer.parseInt(prop.getIndex());
+      Object list;
+      if ("".equals(prop.getName())) {
+        list = object;
+      } else {
+        list = getBeanOrMapProperty(object, prop);
+      }
+      if (list instanceof List) {
+        value = ((List) list).get(i);
+      } else if (list instanceof Object[]) {
+        value = ((Object[]) list)[i];
+      } else if (list instanceof char[]) {
+        value = ((char[]) list)[i];
+      } else if (list instanceof boolean[]) {
+        value = ((boolean[]) list)[i];
+      } else if (list instanceof byte[]) {
+        value = ((byte[]) list)[i];
+      } else if (list instanceof double[]) {
+        value = ((double[]) list)[i];
+      } else if (list instanceof float[]) {
+        value = ((float[]) list)[i];
+      } else if (list instanceof int[]) {
+        value = ((int[]) list)[i];
+      } else if (list instanceof long[]) {
+        value = ((long[]) list)[i];
+      } else if (list instanceof short[]) {
+        value = ((short[]) list)[i];
+      } else {
+        throw new RuntimeException("The '" + prop.getName() + "' property of " + object + " is not a List or Array.");
+      }
+    } catch (RuntimeException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new RuntimeException("Error getting ordinal list from JavaBean. Cause " + e, e);
+    }
+    return value;
+  }
+
+  private void setIndexedProperty(Object object, PropertyTokenizer prop, Object value) {
+    try {
+      int i = Integer.parseInt(prop.getIndex());
+      Object list;
+      if ("".equals(prop.getName())) {
+        list = object;
+      } else {
+        list = getBeanOrMapProperty(object, prop);
+      }
+      if (list instanceof List) {
+        ((List) list).set(i, value);
+      } else if (list instanceof Object[]) {
+        ((Object[]) list)[i] = value;
+      } else if (list instanceof char[]) {
+        ((char[]) list)[i] = (Character) value;
+      } else if (list instanceof boolean[]) {
+        ((boolean[]) list)[i] = (Boolean) value;
+      } else if (list instanceof byte[]) {
+        ((byte[]) list)[i] = (Byte) value;
+      } else if (list instanceof double[]) {
+        ((double[]) list)[i] = (Double) value;
+      } else if (list instanceof float[]) {
+        ((float[]) list)[i] = (Float) value;
+      } else if (list instanceof int[]) {
+        ((int[]) list)[i] = (Integer) value;
+      } else if (list instanceof long[]) {
+        ((long[]) list)[i] = (Long) value;
+      } else if (list instanceof short[]) {
+        ((short[]) list)[i] = (Short) value;
+      } else {
+        throw new RuntimeException("The '" + prop.getName() + "' property of " + object + " is not a List or Array.");
+      }
+    } catch (RuntimeException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new RuntimeException("Error getting ordinal value from JavaBean. Cause " + e, e);
+    }
+  }
+
+  private static class NullObject {
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MethodInvoker.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MethodInvoker.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MethodInvoker.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/MethodInvoker.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,27 @@
+package org.apache.ibatis.reflection;
+
+import java.lang.reflect.*;
+
+class MethodInvoker implements Invoker {
+
+  private Class type;
+  private Method method;
+
+  public MethodInvoker(Method method) {
+    this.method = method;
+
+    if (method.getParameterTypes().length == 1) {
+      type = method.getParameterTypes()[0];
+    } else {
+      type = method.getReturnType();
+    }
+  }
+
+  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
+    return method.invoke(target, args);
+  }
+
+  public Class getType() {
+    return type;
+  }
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ObjectFactory.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ObjectFactory.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ObjectFactory.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/ObjectFactory.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,13 @@
+package org.apache.ibatis.reflection;
+
+import java.util.List;
+
+public interface ObjectFactory {
+
+  Object create(Class type);
+
+  Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs);
+
+  void setProperty(String name, String value);
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyNamer.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyNamer.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyNamer.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyNamer.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,27 @@
+package org.apache.ibatis.reflection;
+
+import java.util.Locale;
+
+public class PropertyNamer {
+
+  public static String methodToProperty(String name) {
+    if (name.startsWith("is")) {
+      name = name.substring(2);
+    } else if (name.startsWith("get") || name.startsWith("set")) {
+      name = name.substring(3);
+    } else {
+      throw new RuntimeException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
+    }
+
+    if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
+      name = name.substring(0, 1).toLowerCase(Locale.US) + name.substring(1);
+    }
+
+    return name;
+  }
+
+  public static boolean isProperty(String name) {
+    return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyTokenizer.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyTokenizer.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyTokenizer.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/PropertyTokenizer.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,59 @@
+package org.apache.ibatis.reflection;
+
+import java.util.Iterator;
+
+class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> {
+  private String name;
+  private String indexedName;
+  private String index;
+  private String children;
+
+  public PropertyTokenizer(String fullname) {
+    int delim = fullname.indexOf('.');
+    if (delim > -1) {
+      name = fullname.substring(0, delim);
+      children = fullname.substring(delim + 1);
+    } else {
+      name = fullname;
+      children = null;
+    }
+    indexedName = name;
+    delim = name.indexOf('[');
+    if (delim > -1) {
+      index = name.substring(delim + 1, name.length() - 1);
+      name = name.substring(0, delim);
+    }
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getIndex() {
+    return index;
+  }
+
+  public String getIndexedName() {
+    return indexedName;
+  }
+
+  public String getChildren() {
+    return children;
+  }
+
+  public boolean hasNext() {
+    return children != null;
+  }
+
+  public PropertyTokenizer next() {
+    return new PropertyTokenizer(children);
+  }
+
+  public void remove() {
+    throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");
+  }
+
+  public Iterator<PropertyTokenizer> iterator() {
+    return this;
+  }
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Reflector.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Reflector.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Reflector.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/Reflector.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,422 @@
+package org.apache.ibatis.reflection;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * This class represents a cached set of class definition information that
+ * allows for easy mapping between property names and getter/setter methods.
+ */
+class Reflector {
+
+  private static boolean classCacheEnabled = true;
+  private static final String[] EMPTY_STRING_ARRAY = new String[0];
+  private static final Map<Class, Reflector> REFLECTOR_MAP = Collections.synchronizedMap(new HashMap<Class, Reflector>());
+
+  private Class type;
+  private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
+  private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
+  private Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
+  private Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
+  private Map<String, Class> setTypes = new HashMap<String, Class>();
+  private Map<String, Class> getTypes = new HashMap<String, Class>();
+  private Constructor defaultConstructor;
+
+  private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();
+
+  private Reflector(Class clazz) {
+    type = clazz;
+    addDefaultConstructor(clazz);
+    addGetMethods(clazz);
+    addSetMethods(clazz);
+    addFields(clazz);
+    readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
+    writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
+    for (String propName : readablePropertyNames) {
+      caseInsensitivePropertyMap.put(propName.toUpperCase(), propName);
+    }
+    for (String propName : writeablePropertyNames) {
+      caseInsensitivePropertyMap.put(propName.toUpperCase(), propName);
+    }
+  }
+
+  private void addDefaultConstructor(Class clazz) {
+    Constructor[] consts = clazz.getDeclaredConstructors();
+    for (Constructor constructor : consts) {
+      if (constructor.getParameterTypes().length == 0) {
+        if (canAccessPrivateMethods()) {
+          try {
+            constructor.setAccessible(true);
+          } catch (Exception e) {
+            // Ignored. This is only a final precaution, nothing we can do.
+          }
+        }
+        if (constructor.isAccessible()) {
+          this.defaultConstructor = constructor;
+        }
+      }
+    }
+  }
+
+  private void addGetMethods(Class cls) {
+    Method[] methods = getAllMethodsForClass(cls);
+    for (Method method : methods) {
+      String name = method.getName();
+      if (name.startsWith("get") && name.length() > 3) {
+        if (method.getParameterTypes().length == 0) {
+          name = PropertyNamer.methodToProperty(name);
+          addGetMethod(name, method);
+        }
+      } else if (name.startsWith("is") && name.length() > 2) {
+        if (method.getParameterTypes().length == 0) {
+          name = PropertyNamer.methodToProperty(name);
+          addGetMethod(name, method);
+        }
+      }
+    }
+  }
+
+  private void addGetMethod(String name, Method method) {
+    if (isValidPropertyName(name)) {
+      getMethods.put(name, new MethodInvoker(method));
+      getTypes.put(name, method.getReturnType());
+    }
+  }
+
+  private void addSetMethods(Class cls) {
+    Map<String, List<Method>> conflictingSetters = new HashMap<String, List<Method>>();
+    Method[] methods = getAllMethodsForClass(cls);
+    for (Method method : methods) {
+      String name = method.getName();
+      if (name.startsWith("set") && name.length() > 3) {
+        if (method.getParameterTypes().length == 1) {
+          name = PropertyNamer.methodToProperty(name);
+          addSetterConflict(conflictingSetters, name, method);
+        }
+      }
+    }
+    resolveSetterConflicts(conflictingSetters);
+  }
+
+  private void addSetterConflict(Map<String, List<Method>> conflictingSetters, String name, Method method) {
+    List<Method> list = conflictingSetters.get(name);
+    if (list == null) {
+      list = new ArrayList<Method>();
+      conflictingSetters.put(name, list);
+    }
+    list.add(method);
+  }
+
+  private void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) {
+    for (String propName : conflictingSetters.keySet()) {
+      List<Method> setters = conflictingSetters.get(propName);
+      Method firstMethod = setters.get(0);
+      if (setters.size() == 1) {
+        addSetMethod(propName, firstMethod);
+      } else {
+        Class expectedType = getTypes.get(propName);
+        if (expectedType == null) {
+          throw new RuntimeException("Illegal overloaded setter method with ambiguous type for property "
+              + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " +
+              "specification and can cause unpredicatble results.");
+        } else {
+          Iterator<Method> methods = setters.iterator();
+          Method setter = null;
+          while (methods.hasNext()) {
+            Method method = methods.next();
+            if (method.getParameterTypes().length == 1
+                && expectedType.equals(method.getParameterTypes()[0])) {
+              setter = method;
+              break;
+            }
+          }
+          if (setter == null) {
+            throw new RuntimeException("Illegal overloaded setter method with ambiguous type for property "
+                + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " +
+                "specification and can cause unpredicatble results.");
+          }
+          addSetMethod(propName, setter);
+        }
+      }
+    }
+  }
+
+  private void addSetMethod(String name, Method method) {
+    if (isValidPropertyName(name)) {
+      setMethods.put(name, new MethodInvoker(method));
+      setTypes.put(name, method.getParameterTypes()[0]);
+    }
+  }
+
+  private void addFields(Class clazz) {
+    Field[] fields = clazz.getDeclaredFields();
+    for (Field field : fields) {
+      if (canAccessPrivateMethods()) {
+        try {
+          field.setAccessible(true);
+        } catch (Exception e) {
+          // Ignored. This is only a final precaution, nothing we can do.
+        }
+      }
+      if (field.isAccessible()) {
+        if (!setMethods.containsKey(field.getName())) {
+          if (!Modifier.isFinal(field.getModifiers())) {
+            addSetField(field);
+          }
+        }
+        if (!getMethods.containsKey(field.getName())) {
+          addGetField(field);
+        }
+      }
+    }
+    if (clazz.getSuperclass() != null) {
+      addFields(clazz.getSuperclass());
+    }
+  }
+
+  private void addSetField(Field field) {
+    if (isValidPropertyName(field.getName())) {
+      setMethods.put(field.getName(), new SetFieldInvoker(field));
+      setTypes.put(field.getName(), field.getType());
+    }
+  }
+
+  private void addGetField(Field field) {
+    if (isValidPropertyName(field.getName())) {
+      getMethods.put(field.getName(), new GetFieldInvoker(field));
+      getTypes.put(field.getName(), field.getType());
+    }
+  }
+
+  private boolean isValidPropertyName(String name) {
+    return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
+  }
+
+  private Method[] getAllMethodsForClass(Class cls) {
+    if (cls.isInterface()) {
+      // interfaces only have public methods - so the
+      // simple call is all we need (this will also get superinterface methods)
+      return cls.getMethods();
+    } else {
+      // need to get all the declared methods in this class
+      // and any super-class - then need to set access appropriatly
+      // for private methods
+      return getClassMethods(cls);
+    }
+  }
+
+  /**
+   * This method returns an array containing all methods
+   * declared in this class and any superclass.
+   * We use this method, instead of the simpler Class.getMethods(),
+   * because we want to look for private methods as well.
+   *
+   * @param cls The class
+   * @return An array containing all methods in this class
+   */
+  private Method[] getClassMethods(Class cls) {
+    HashMap<String, Method> uniqueMethods = new HashMap<String, Method>();
+    Class currentClass = cls;
+    while (currentClass != null) {
+      addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
+
+      // we also need to look for interface methods - 
+      // because the class may be abstract
+      Class[] interfaces = currentClass.getInterfaces();
+      for (Class anInterface : interfaces) {
+        addUniqueMethods(uniqueMethods, anInterface.getMethods());
+      }
+
+      currentClass = currentClass.getSuperclass();
+    }
+
+    Collection<Method> methods = uniqueMethods.values();
+
+    return methods.toArray(new Method[methods.size()]);
+  }
+
+  private void addUniqueMethods(HashMap<String, Method> uniqueMethods, Method[] methods) {
+    for (Method currentMethod : methods) {
+      String signature = getSignature(currentMethod);
+      // check to see if the method is already known
+      // if it is known, then an extended class must have
+      // overridden a method
+      if (!uniqueMethods.containsKey(signature)) {
+        if (canAccessPrivateMethods()) {
+          try {
+            currentMethod.setAccessible(true);
+          } catch (Exception e) {
+            // Ignored. This is only a final precaution, nothing we can do.
+          }
+        }
+
+        uniqueMethods.put(signature, currentMethod);
+      }
+    }
+  }
+
+  private String getSignature(Method method) {
+    StringBuffer sb = new StringBuffer();
+    sb.append(method.getName());
+    Class[] parameters = method.getParameterTypes();
+
+    for (int i = 0; i < parameters.length; i++) {
+      if (i == 0) {
+        sb.append(':');
+      } else {
+        sb.append(',');
+      }
+      sb.append(parameters[i].getName());
+    }
+
+    return sb.toString();
+  }
+
+  private static boolean canAccessPrivateMethods() {
+    try {
+      SecurityManager securityManager = System.getSecurityManager();
+      if (null != securityManager) {
+        securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
+      }
+    } catch (SecurityException e) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Gets the name of the class the instance provides information for
+   *
+   * @return The class name
+   */
+  public Class getType() {
+    return type;
+  }
+
+  public Constructor getDefaultConstructor() {
+    if (defaultConstructor != null) {
+      return defaultConstructor;
+    } else {
+      throw new RuntimeException("There is no default constructor for " + type);
+    }
+  }
+
+  public Invoker getSetInvoker(String propertyName) {
+    Invoker method = setMethods.get(propertyName);
+    if (method == null) {
+      throw new RuntimeException("There is no setter for property named '" + propertyName + "' in '" + type + "'");
+    }
+    return method;
+  }
+
+  public Invoker getGetInvoker(String propertyName) {
+    Invoker method = getMethods.get(propertyName);
+    if (method == null) {
+      throw new RuntimeException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
+    }
+    return method;
+  }
+
+  /**
+   * Gets the type for a property setter
+   *
+   * @param propertyName - the name of the property
+   * @return The Class of the propery setter
+   */
+  public Class getSetterType(String propertyName) {
+    Class clazz = setTypes.get(propertyName);
+    if (clazz == null) {
+      throw new RuntimeException("There is no setter for property named '" + propertyName + "' in '" + type + "'");
+    }
+    return clazz;
+  }
+
+  /**
+   * Gets the type for a property getter
+   *
+   * @param propertyName - the name of the property
+   * @return The Class of the propery getter
+   */
+  public Class getGetterType(String propertyName) {
+    Class clazz = getTypes.get(propertyName);
+    if (clazz == null) {
+      throw new RuntimeException("There is no getter for property named '" + propertyName + "' in '" + type + "'");
+    }
+    return clazz;
+  }
+
+  /**
+   * Gets an array of the readable properties for an object
+   *
+   * @return The array
+   */
+  public String[] getGetablePropertyNames() {
+    return readablePropertyNames;
+  }
+
+  /**
+   * Gets an array of the writeable properties for an object
+   *
+   * @return The array
+   */
+  public String[] getSetablePropertyNames() {
+    return writeablePropertyNames;
+  }
+
+  /**
+   * Check to see if a class has a writeable property by name
+   *
+   * @param propertyName - the name of the property to check
+   * @return True if the object has a writeable property by the name
+   */
+  public boolean hasSetter(String propertyName) {
+    return setMethods.keySet().contains(propertyName);
+  }
+
+  /**
+   * Check to see if a class has a readable property by name
+   *
+   * @param propertyName - the name of the property to check
+   * @return True if the object has a readable property by the name
+   */
+  public boolean hasGetter(String propertyName) {
+    return getMethods.keySet().contains(propertyName);
+  }
+
+  public String findPropertyName(String name) {
+    return caseInsensitivePropertyMap.get(name.toUpperCase());
+  }
+
+  /**
+   * Gets an instance of ClassInfo for the specified class.
+   *
+   * @param clazz The class for which to lookup the method cache.
+   * @return The method cache for the class
+   */
+  public static Reflector forClass(Class clazz) {
+    if (classCacheEnabled) {
+      synchronized (clazz) {
+        Reflector cached = REFLECTOR_MAP.get(clazz);
+        if (cached == null) {
+          cached = new Reflector(clazz);
+          REFLECTOR_MAP.put(clazz, cached);
+        }
+        return cached;
+      }
+    } else {
+      return new Reflector(clazz);
+    }
+  }
+
+  public static void setClassCacheEnabled(boolean classCacheEnabled) {
+    Reflector.classCacheEnabled = classCacheEnabled;
+  }
+
+  public static boolean isClassCacheEnabled() {
+    return classCacheEnabled;
+  }
+
+}
+
+
+

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/SetFieldInvoker.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/SetFieldInvoker.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/SetFieldInvoker.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/reflection/SetFieldInvoker.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,20 @@
+package org.apache.ibatis.reflection;
+
+import java.lang.reflect.*;
+
+class SetFieldInvoker implements Invoker {
+  private Field field;
+
+  public SetFieldInvoker(Field field) {
+    this.field = field;
+  }
+
+  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
+    field.set(target, args[0]);
+    return null;
+  }
+
+  public Class getType() {
+    return field.getType();
+  }
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BaseTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BaseTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BaseTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BaseTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,49 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public abstract class BaseTypeHandler implements TypeHandler {
+
+  public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    if (parameter == null) {
+      if (jdbcType == null) {
+        throw new RuntimeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
+      }
+      ps.setNull(i, jdbcType.TYPE_CODE);
+    } else {
+      setNonNullParameter(ps, i, parameter, jdbcType);
+    }
+  }
+
+  public Object getResult(ResultSet rs, String columnName)
+      throws SQLException {
+    Object result = getNullableResult(rs, columnName);
+    if (rs.wasNull()) {
+      return null;
+    } else {
+      return result;
+    }
+  }
+
+  public Object getResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    Object result = getNullableResult(cs, columnIndex);
+    if (cs.wasNull()) {
+      return null;
+    } else {
+      return result;
+    }
+  }
+
+  public abstract void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException;
+
+  public abstract Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException;
+
+  public abstract Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException;
+
+}
+

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BigDecimalTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BigDecimalTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BigDecimalTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BigDecimalTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,24 @@
+package org.apache.ibatis.type;
+
+import java.math.BigDecimal;
+import java.sql.*;
+
+public class BigDecimalTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setBigDecimal(i, ((BigDecimal) parameter));
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getBigDecimal(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getBigDecimal(columnIndex);
+  }
+
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BlobTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BlobTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BlobTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BlobTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,35 @@
+package org.apache.ibatis.type;
+
+import java.io.ByteArrayInputStream;
+import java.sql.*;
+
+public class BlobTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    byte[] bytes = (byte[]) parameter;
+    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+    ps.setBinaryStream(i, bis, bytes.length);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    Blob blob = rs.getBlob(columnName);
+    byte[] returnValue = null;
+    if (null != blob) {
+      returnValue = blob.getBytes(1, (int) blob.length());
+    }
+    return returnValue;
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    Blob blob = cs.getBlob(columnIndex);
+    byte[] returnValue = null;
+    if (null != blob) {
+      returnValue = blob.getBytes(1, (int) blob.length());
+    }
+    return returnValue;
+  }
+
+}
\ No newline at end of file

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BooleanTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BooleanTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BooleanTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/BooleanTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,23 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class BooleanTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setBoolean(i, (Boolean) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getBoolean(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getBoolean(columnIndex);
+  }
+
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteArrayTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteArrayTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteArrayTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteArrayTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,23 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class ByteArrayTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setBytes(i, (byte[]) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getBytes(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getBytes(columnIndex);
+  }
+
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ByteTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,23 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class ByteTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setByte(i, (Byte) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getByte(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getByte(columnIndex);
+  }
+
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ClobTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ClobTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ClobTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ClobTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,38 @@
+package org.apache.ibatis.type;
+
+import java.io.StringReader;
+import java.sql.*;
+
+public class ClobTypeHandler extends BaseTypeHandler {
+
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    String s = (String) parameter;
+    StringReader reader = new StringReader(s);
+    ps.setCharacterStream(i, reader, s.length());
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    String value = "";
+    Clob clob = rs.getClob(columnName);
+    if (clob != null) {
+      int size = (int) clob.length();
+      value = clob.getSubString(1, size);
+    }
+    return value;
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    String value = "";
+    Clob clob = cs.getClob(columnIndex);
+    if (clob != null) {
+      int size = (int) clob.length();
+      value = clob.getSubString(1, size);
+    }
+    return value;
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateOnlyTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateOnlyTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateOnlyTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateOnlyTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,31 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+import java.util.Date;
+
+public class DateOnlyTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setDate(i, new java.sql.Date(((Date) parameter).getTime()));
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    java.sql.Date sqlDate = rs.getDate(columnName);
+    if (sqlDate != null) {
+      return new java.util.Date(sqlDate.getTime());
+    }
+    return null;
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    java.sql.Date sqlDate = cs.getDate(columnIndex);
+    if (sqlDate != null) {
+      return new java.util.Date(sqlDate.getTime());
+    }
+    return null;
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DateTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,31 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+import java.util.Date;
+
+public class DateTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setTimestamp(i, new java.sql.Timestamp(((Date) parameter).getTime()));
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    java.sql.Timestamp sqlTimestamp = rs.getTimestamp(columnName);
+    if (sqlTimestamp != null) {
+      return new java.util.Date(sqlTimestamp.getTime());
+    }
+    return null;
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    java.sql.Timestamp sqlTimestamp = cs.getTimestamp(columnIndex);
+    if (sqlTimestamp != null) {
+      return new java.util.Date(sqlTimestamp.getTime());
+    }
+    return null;
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DoubleTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DoubleTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DoubleTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/DoubleTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,22 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class DoubleTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setDouble(i, (Double) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getDouble(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getDouble(columnIndex);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/EnumTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/EnumTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/EnumTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/EnumTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,27 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class EnumTypeHandler extends BaseTypeHandler implements TypeHandler {
+
+  private Class type;
+
+  public EnumTypeHandler(Class type) {
+    this.type = type;
+  }
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
+    ps.setString(i, parameter.toString());
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
+    String s = rs.getString(columnName);
+    return s == null ? null : Enum.valueOf(type, s);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+    String s = cs.getString(columnIndex);
+    return s == null ? null : Enum.valueOf(type, s);
+  }
+
+}
\ No newline at end of file

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/FloatTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/FloatTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/FloatTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/FloatTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,22 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class FloatTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setFloat(i, (Float) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getFloat(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getFloat(columnIndex);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/IntegerTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/IntegerTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/IntegerTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/IntegerTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,22 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class IntegerTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setInt(i, (Integer) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getInt(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getInt(columnIndex);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/JdbcType.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/JdbcType.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/JdbcType.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/JdbcType.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,50 @@
+package org.apache.ibatis.type;
+
+import java.sql.Types;
+
+public enum JdbcType {
+
+  BIT(Types.BIT),
+  TINYINT(Types.TINYINT),
+  SMALLINT(Types.SMALLINT),
+  INTEGER(Types.INTEGER),
+  BIGINT(Types.BIGINT),
+  FLOAT(Types.FLOAT),
+  REAL(Types.REAL),
+  DOUBLE(Types.DOUBLE),
+  NUMERIC(Types.NUMERIC),
+  DECIMAL(Types.DECIMAL),
+  CHAR(Types.CHAR),
+  VARCHAR(Types.VARCHAR),
+  LONGVARCHAR(Types.LONGVARCHAR),
+  DATE(Types.DATE),
+  TIME(Types.TIME),
+  TIMESTAMP(Types.TIMESTAMP),
+  BINARY(Types.BINARY),
+  VARBINARY(Types.VARBINARY),
+  LONGVARBINARY(Types.LONGVARBINARY),
+  NULL(Types.NULL),
+  OTHER(Types.OTHER),
+  BLOB(Types.BLOB),
+  CLOB(Types.CLOB),
+  BOOLEAN(Types.BOOLEAN),
+  CURSOR(-10), // Oracle
+  UNDEFINED(Integer.MIN_VALUE + 1000);
+
+  // ----------------
+  // -- Unsupported--
+  // ----------------
+  //JAVA_OBJECT(Types.JAVA_OBJECT),
+  //DISTINCT(Types.DISTINCT),
+  //STRUCT(Types.STRUCT),
+  //ARRAY(Types.ARRAY),
+  //REF(Types.REF),
+  //DATALINK(Types.DATALINK),
+
+  public final int TYPE_CODE;
+
+  JdbcType(int code) {
+    this.TYPE_CODE = code;
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/LongTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/LongTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/LongTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/LongTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,22 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class LongTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setLong(i, (Long) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getLong(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getLong(columnIndex);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ObjectTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ObjectTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ObjectTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ObjectTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,22 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class ObjectTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setObject(i, parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getObject(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getObject(columnIndex);
+  }
+
+}

Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ShortTypeHandler.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ShortTypeHandler.java?rev=683745&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ShortTypeHandler.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/type/ShortTypeHandler.java Thu Aug  7 16:21:46 2008
@@ -0,0 +1,22 @@
+package org.apache.ibatis.type;
+
+import java.sql.*;
+
+public class ShortTypeHandler extends BaseTypeHandler {
+
+  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
+      throws SQLException {
+    ps.setShort(i, (Short) parameter);
+  }
+
+  public Object getNullableResult(ResultSet rs, String columnName)
+      throws SQLException {
+    return rs.getShort(columnName);
+  }
+
+  public Object getNullableResult(CallableStatement cs, int columnIndex)
+      throws SQLException {
+    return cs.getShort(columnIndex);
+  }
+
+}