ibatis/0000755000175000017500000000000011110613053012256 5ustar twernertwerneribatis/META-INF/0000755000175000017500000000000011061424574013433 5ustar twernertwerneribatis/META-INF/MANIFEST.MF0000644000175000017500000000015311061424572015062 0ustar twernertwernerManifest-Version: 1.0 Ant-Version: Apache Ant 1.5.3 Created-By: 1.5.0_12-b04 (Sun Microsystems Inc.) ibatis/doc/0000755000175000017500000000000011061424572013036 5ustar twernertwerneribatis/lib/0000755000175000017500000000000011061424572013037 5ustar twernertwerneribatis/simple_example/0000755000175000017500000000000011061424422015267 5ustar twernertwerneribatis/simple_example/com/0000755000175000017500000000000011061424422016045 5ustar twernertwerneribatis/simple_example/com/mydomain/0000755000175000017500000000000011061424422017662 5ustar twernertwerneribatis/simple_example/com/mydomain/data/0000755000175000017500000000000011061424422020573 5ustar twernertwerneribatis/simple_example/com/mydomain/data/Account.xml0000644000175000017500000000434111061424422022713 0ustar twernertwerner insert into ACCOUNT ( ACC_ID, ACC_FIRST_NAME, ACC_LAST_NAME, ACC_EMAIL values ( #id#, #firstName#, #lastName#, #emailAddress# ) update ACCOUNT set ACC_FIRST_NAME = #firstName#, ACC_LAST_NAME = #lastName#, ACC_EMAIL = #emailAddress# where ACC_ID = #id# delete from ACCOUNT where ACC_ID = #id# ibatis/simple_example/com/mydomain/data/SimpleExample.java0000644000175000017500000000364511061424422024213 0ustar twernertwernerpackage com.mydomain.data; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; import com.ibatis.common.resources.Resources; import com.mydomain.domain.Account; import java.io.Reader; import java.io.IOException; import java.util.List; import java.sql.SQLException; /** * This is not a best practices class. It's just an example * to give you an idea of how iBATIS works. For a more complete * example, see JPetStore 5.0 at http://www.ibatis.com. */ public class SimpleExample { /** * SqlMapClient instances are thread safe, so you only need one. * In this case, we'll use a static singleton. So sue me. ;-) */ private static SqlMapClient sqlMapper; /** * It's not a good idea to put code that can fail in a class initializer, * but for sake of argument, here's how you configure an SQL Map. */ static { try { Reader reader = Resources.getResourceAsReader("com/mydomain/data/SqlMapConfig.xml"); sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader); reader.close(); } catch (IOException e) { // Fail fast. throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e); } } public static List selectAllAccounts () throws SQLException { return sqlMapper.queryForList("selectAllAccounts"); } public static Account selectAccountById (int id) throws SQLException { return (Account) sqlMapper.queryForObject("selectAccountById", id); } public static void insertAccount (Account account) throws SQLException { sqlMapper.insert("insertAccount", account); } public static void updateAccount (Account account) throws SQLException { sqlMapper.update("updateAccount", account); } public static void deleteAccount (int id) throws SQLException { sqlMapper.delete("deleteAccount", id); } } ibatis/simple_example/com/mydomain/data/SqlMapConfig.xml0000644000175000017500000000213011061424422023634 0ustar twernertwerner ibatis/simple_example/com/mydomain/domain/0000755000175000017500000000000011061424422021131 5ustar twernertwerneribatis/simple_example/com/mydomain/domain/Account.java0000644000175000017500000000134711061424422023375 0ustar twernertwernerpackage com.mydomain.domain; public class Account { private int id; private String firstName; private String lastName; private String emailAddress; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } } ibatis/simple_example/README.TXT0000644000175000017500000000103011061424422016617 0ustar twernertwernerWelcome! This classpath contains a VERY simple example of how iBATIS can be configured and used. It is NOT a best practices example, instead it shows you the basics of iBATIS in the simplest form possible (i.e. lots of static methods ;-) Browse through it, get a feel for it. If you like, you can copy the XML files to your own project to use as a starting point. For a more complete example - and best practices - please see the JPetStore example application at http://www.ibatis.com Best regards, Clinton Beginibatis/src/0000755000175000017500000000000011110613054013046 5ustar twernertwerneribatis/src/META-INF/0000755000175000017500000000000011061424572014220 5ustar twernertwerneribatis/src/META-INF/MANIFEST.MF0000644000175000017500000000015311061424570015647 0ustar twernertwernerManifest-Version: 1.0 Ant-Version: Apache Ant 1.5.3 Created-By: 1.5.0_12-b04 (Sun Microsystems Inc.) ibatis/src/com/0000755000175000017500000000000011047641626013643 5ustar twernertwerneribatis/src/com/ibatis/0000755000175000017500000000000011047641630015111 5ustar twernertwerneribatis/src/com/ibatis/common/0000755000175000017500000000000011047641630016401 5ustar twernertwerneribatis/src/com/ibatis/common/beans/0000755000175000017500000000000011047641630017471 5ustar twernertwerneribatis/src/com/ibatis/common/beans/BaseProbe.java0000644000175000017500000001454411047641630022206 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; import java.util.List; /** * Abstract class used to help development of Probe implementations */ public abstract class BaseProbe implements Probe { protected abstract void setProperty(Object object, String property, Object value); protected abstract Object getProperty(Object object, String property); /** * Returns an array of the readable properties exposed by an object * * @param object - the object * @return The array of property names */ public abstract String[] getReadablePropertyNames(Object object); /** * Returns an array of the writeable properties exposed by an object * * @param object - the object * @return The array of property names */ public abstract String[] getWriteablePropertyNames(Object object); protected Object getIndexedProperty(Object object, String indexedName) { Object value = null; try { String name = indexedName.substring(0, indexedName.indexOf('[')); int i = Integer.parseInt(indexedName.substring(indexedName.indexOf('[') + 1, indexedName.indexOf(']'))); Object list = null; if("".equals(name)) { list = object; } else { list = getProperty(object, name); } if (list instanceof List) { value = ((List) list).get(i); } else if (list instanceof Object[]) { value = ((Object[]) list)[i]; } else if (list instanceof char[]) { value = new Character(((char[]) list)[i]); } else if (list instanceof boolean[]) { value = new Boolean(((boolean[]) list)[i]); } else if (list instanceof byte[]) { value = new Byte(((byte[]) list)[i]); } else if (list instanceof double[]) { value = new Double(((double[]) list)[i]); } else if (list instanceof float[]) { value = new Float(((float[]) list)[i]); } else if (list instanceof int[]) { value = new Integer(((int[]) list)[i]); } else if (list instanceof long[]) { value = new Long(((long[]) list)[i]); } else if (list instanceof short[]) { value = new Short(((short[]) list)[i]); } else { throw new ProbeException("The '" + name + "' property of the " + object.getClass().getName() + " class is not a List or Array."); } } catch (ProbeException e) { throw e; } catch (Exception e) { throw new ProbeException("Error getting ordinal list from JavaBean. Cause " + e, e); } return value; } protected Class getIndexedType(Object object, String indexedName) { Class value = null; try { String name = indexedName.substring(0, indexedName.indexOf('[')); int i = Integer.parseInt(indexedName.substring(indexedName.indexOf('[') + 1, indexedName.indexOf(']'))); Object list = null; if(!"".equals(name)) { list = getProperty(object, name); } else { list = object; } if (list instanceof List) { value = ((List) list).get(i).getClass(); } else if (list instanceof Object[]) { value = ((Object[]) list)[i].getClass(); } else if (list instanceof char[]) { value = Character.class; } else if (list instanceof boolean[]) { value = Boolean.class; } else if (list instanceof byte[]) { value = Byte.class; } else if (list instanceof double[]) { value = Double.class; } else if (list instanceof float[]) { value = Float.class; } else if (list instanceof int[]) { value = Integer.class; } else if (list instanceof long[]) { value = Long.class; } else if (list instanceof short[]) { value = Short.class; } else { throw new ProbeException("The '" + name + "' property of the " + object.getClass().getName() + " class is not a List or Array."); } } catch (ProbeException e) { throw e; } catch (Exception e) { throw new ProbeException("Error getting ordinal list from JavaBean. Cause " + e, e); } return value; } protected void setIndexedProperty(Object object, String indexedName, Object value) { try { String name = indexedName.substring(0, indexedName.indexOf('[')); int i = Integer.parseInt(indexedName.substring(indexedName.indexOf('[') + 1, indexedName.indexOf(']'))); Object list = getProperty(object, name); 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).charValue(); } else if (list instanceof boolean[]) { ((boolean[]) list)[i] = ((Boolean) value).booleanValue(); } else if (list instanceof byte[]) { ((byte[]) list)[i] = ((Byte) value).byteValue(); } else if (list instanceof double[]) { ((double[]) list)[i] = ((Double) value).doubleValue(); } else if (list instanceof float[]) { ((float[]) list)[i] = ((Float) value).floatValue(); } else if (list instanceof int[]) { ((int[]) list)[i] = ((Integer) value).intValue(); } else if (list instanceof long[]) { ((long[]) list)[i] = ((Long) value).longValue(); } else if (list instanceof short[]) { ((short[]) list)[i] = ((Short) value).shortValue(); } else { throw new ProbeException("The '" + name + "' property of the " + object.getClass().getName() + " class is not a List or Array."); } } catch (ProbeException e) { throw e; } catch (Exception e) { throw new ProbeException("Error getting ordinal value from JavaBean. Cause " + e, e); } } } ibatis/src/com/ibatis/common/beans/ClassInfo.java0000644000175000017500000004304711056460676022236 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; import java.lang.reflect.*; import java.math.*; 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. */ public class ClassInfo { private static boolean cacheEnabled = true; private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final Set SIMPLE_TYPE_SET = new HashSet(); private static final Map CLASS_INFO_MAP = Collections.synchronizedMap(new HashMap()); private String className; private String[] readablePropertyNames = EMPTY_STRING_ARRAY; private String[] writeablePropertyNames = EMPTY_STRING_ARRAY; private HashMap setMethods = new HashMap(); private HashMap getMethods = new HashMap(); private HashMap setTypes = new HashMap(); private HashMap getTypes = new HashMap(); private Constructor defaultConstructor; static { SIMPLE_TYPE_SET.add(String.class); SIMPLE_TYPE_SET.add(Byte.class); SIMPLE_TYPE_SET.add(Short.class); SIMPLE_TYPE_SET.add(Character.class); SIMPLE_TYPE_SET.add(Integer.class); SIMPLE_TYPE_SET.add(Long.class); SIMPLE_TYPE_SET.add(Float.class); SIMPLE_TYPE_SET.add(Double.class); SIMPLE_TYPE_SET.add(Boolean.class); SIMPLE_TYPE_SET.add(Date.class); SIMPLE_TYPE_SET.add(Class.class); SIMPLE_TYPE_SET.add(BigInteger.class); SIMPLE_TYPE_SET.add(BigDecimal.class); SIMPLE_TYPE_SET.add(Collection.class); SIMPLE_TYPE_SET.add(Set.class); SIMPLE_TYPE_SET.add(Map.class); SIMPLE_TYPE_SET.add(List.class); SIMPLE_TYPE_SET.add(HashMap.class); SIMPLE_TYPE_SET.add(TreeMap.class); SIMPLE_TYPE_SET.add(ArrayList.class); SIMPLE_TYPE_SET.add(LinkedList.class); SIMPLE_TYPE_SET.add(HashSet.class); SIMPLE_TYPE_SET.add(TreeSet.class); SIMPLE_TYPE_SET.add(Vector.class); SIMPLE_TYPE_SET.add(Hashtable.class); SIMPLE_TYPE_SET.add(Enumeration.class); } private ClassInfo(Class clazz) { className = clazz.getName(); addDefaultConstructor(clazz); addGetMethods(clazz); addSetMethods(clazz); addFields(clazz); readablePropertyNames = (String[]) getMethods.keySet().toArray(new String[getMethods.keySet().size()]); writeablePropertyNames = (String[]) setMethods.keySet().toArray(new String[setMethods.keySet().size()]); } private void addDefaultConstructor(Class clazz) { Constructor[] consts = clazz.getDeclaredConstructors(); for (int i = 0; i < consts.length; i++) { Constructor constructor = consts[i]; 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 = getClassMethods(cls); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; String name = method.getName(); if (name.startsWith("get") && name.length() > 3) { if (method.getParameterTypes().length == 0) { name = dropCase(name); addGetMethod(name, method); } } else if (name.startsWith("is") && name.length() > 2) { if (method.getParameterTypes().length == 0) { name = dropCase(name); addGetMethod(name, method); } } } } private void addGetMethod(String name, Method method) { getMethods.put(name, new MethodInvoker(method)); getTypes.put(name, method.getReturnType()); } private void addSetMethods(Class cls) { Map conflictingSetters = new HashMap(); Method[] methods = getClassMethods(cls); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; String name = method.getName(); if (name.startsWith("set") && name.length() > 3) { if (method.getParameterTypes().length == 1) { name = dropCase(name); ///------------ addSetterConflict(conflictingSetters, name, method); // addSetMethod(name, method); ///------------ } } } resolveSetterConflicts(conflictingSetters); } private void addSetterConflict(Map conflictingSetters, String name, Method method) { List list = (List) conflictingSetters.get(name); if (list == null) { list = new ArrayList(); conflictingSetters.put(name, list); } list.add(method); } private void resolveSetterConflicts(Map conflictingSetters) { for (Iterator propNames = conflictingSetters.keySet().iterator(); propNames.hasNext();) { String propName = (String) propNames.next(); List setters = (List) conflictingSetters.get(propName); Method firstMethod = (Method) setters.get(0); if (setters.size() == 1) { addSetMethod(propName, firstMethod); } else { Class expectedType = (Class) 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 methods = setters.iterator(); Method setter = null; while (methods.hasNext()) { Method 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) { setMethods.put(name, new MethodInvoker(method)); setTypes.put(name, method.getParameterTypes()[0]); } private void addFields(Class clazz) { Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; 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())) { addSetField(field); } if (!getMethods.containsKey(field.getName())) { addGetField(field); } } } if (clazz.getSuperclass() != null) { addFields(clazz.getSuperclass()); } } private void addSetField(Field field) { setMethods.put(field.getName(), new SetFieldInvoker(field)); setTypes.put(field.getName(), field.getType()); } private void addGetField(Field field) { getMethods.put(field.getName(), new GetFieldInvoker(field)); getTypes.put(field.getName(), field.getType()); } /** * 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 uniqueMethods = new HashMap(); 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 (int i = 0; i < interfaces.length; i++) { addUniqueMethods(uniqueMethods, interfaces[i].getMethods()); } currentClass = currentClass.getSuperclass(); } Collection methods = uniqueMethods.values(); return (Method[]) methods.toArray(new Method[methods.size()]); } private void addUniqueMethods(HashMap uniqueMethods, Method[] methods) { for (Method currentMethod : methods) { if (!currentMethod.isBridge()) { 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 String dropCase(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 ProbeException("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; } 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 String getClassName() { return className; } public Object instantiateClass() { if (defaultConstructor != null) { try { return defaultConstructor.newInstance(null); } catch (Exception e) { throw new RuntimeException("Error instantiating class. Cause: " + e, e); } } else { throw new RuntimeException("Error instantiating class. There is no default constructor for class " + className); } } /** * Gets the setter for a property as a Method object * * @param propertyName - the property * @return The Method */ public Method getSetter(String propertyName) { Invoker method = (Invoker) setMethods.get(propertyName); if (method == null) { throw new ProbeException("There is no WRITEABLE property named '" + propertyName + "' in class '" + className + "'"); } if (!(method instanceof MethodInvoker)) { throw new ProbeException("Can't get setter method because '" + propertyName + "' is a field in class '" + className + "'"); } return ((MethodInvoker) method).getMethod(); } /** * Gets the getter for a property as a Method object * * @param propertyName - the property * @return The Method */ public Method getGetter(String propertyName) { Invoker method = (Invoker) getMethods.get(propertyName); if (method == null) { throw new ProbeException("There is no READABLE property named '" + propertyName + "' in class '" + className + "'"); } if (!(method instanceof MethodInvoker)) { throw new ProbeException("Can't get getter method because '" + propertyName + "' is a field in class '" + className + "'"); } return ((MethodInvoker) method).getMethod(); } public Invoker getSetInvoker(String propertyName) { Invoker method = (Invoker) setMethods.get(propertyName); if (method == null) { throw new ProbeException("There is no WRITEABLE property named '" + propertyName + "' in class '" + className + "'"); } return method; } public Invoker getGetInvoker(String propertyName) { Invoker method = (Invoker) getMethods.get(propertyName); if (method == null) { throw new ProbeException("There is no READABLE property named '" + propertyName + "' in class '" + className + "'"); } 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 = (Class) setTypes.get(propertyName); if (clazz == null) { throw new ProbeException("There is no WRITEABLE property named '" + propertyName + "' in class '" + className + "'"); } 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 = (Class) getTypes.get(propertyName); if (clazz == null) { throw new ProbeException("There is no READABLE property named '" + propertyName + "' in class '" + className + "'"); } return clazz; } /** * Gets an array of the readable properties for an object * * @return The array */ public String[] getReadablePropertyNames() { return readablePropertyNames; } /** * Gets an array of the writeable properties for an object * * @return The array */ public String[] getWriteablePropertyNames() { 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 hasWritableProperty(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 hasReadableProperty(String propertyName) { return getMethods.keySet().contains(propertyName); } /** * Tells us if the class passed in is a knwon common type * * @param clazz The class to check * @return True if the class is known */ public static boolean isKnownType(Class clazz) { if (SIMPLE_TYPE_SET.contains(clazz)) { return true; } else if (Collection.class.isAssignableFrom(clazz)) { return true; } else if (Map.class.isAssignableFrom(clazz)) { return true; } else if (List.class.isAssignableFrom(clazz)) { return true; } else if (Set.class.isAssignableFrom(clazz)) { return true; } else if (Iterator.class.isAssignableFrom(clazz)) { return true; } else { return false; } } /** * 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 ClassInfo getInstance(Class clazz) { if (cacheEnabled) { synchronized (clazz) { ClassInfo cached = (ClassInfo) CLASS_INFO_MAP.get(clazz); if (cached == null) { cached = new ClassInfo(clazz); CLASS_INFO_MAP.put(clazz, cached); } return cached; } } else { return new ClassInfo(clazz); } } public static void setCacheEnabled(boolean cacheEnabled) { ClassInfo.cacheEnabled = cacheEnabled; } /** * Examines a Throwable object and gets it's root cause * * @param t - the exception to examine * @return The root cause */ public static Throwable unwrapThrowable(Throwable t) { Throwable t2 = t; while (true) { if (t2 instanceof InvocationTargetException) { t2 = ((InvocationTargetException) t).getTargetException(); } else if (t instanceof UndeclaredThrowableException) { t2 = ((UndeclaredThrowableException) t).getUndeclaredThrowable(); } else { return t2; } } } } ibatis/src/com/ibatis/common/beans/ComplexBeanProbe.java0000644000175000017500000003051011047641630023520 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; import java.util.Map; import java.util.StringTokenizer; import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil; /** * StaticBeanProbe provides methods that allow simple, reflective access to * JavaBeans style properties. Methods are provided for all simple types as * well as object types. *

* Examples: *

* StaticBeanProbe.setObject(object, propertyName, value); *

* Object value = StaticBeanProbe.getObject(object, propertyName); */ public class ComplexBeanProbe extends BaseProbe { private static final Object[] NO_ARGUMENTS = new Object[0]; protected ComplexBeanProbe() { } /** * Returns an array of the readable properties exposed by a bean * * @param object The bean * @return The properties */ public String[] getReadablePropertyNames(Object object) { return ClassInfo.getInstance(object.getClass()).getReadablePropertyNames(); } /** * Returns an array of the writeable properties exposed by a bean * * @param object The bean * @return The properties */ public String[] getWriteablePropertyNames(Object object) { return ClassInfo.getInstance(object.getClass()).getWriteablePropertyNames(); } /** * Returns the class that the setter expects to receive as a parameter when * setting a property value. * * @param object The bean to check * @param name The name of the property * @return The type of the property */ public Class getPropertyTypeForSetter(Object object, String name) { Class type = object.getClass(); if (object instanceof Class) { type = getClassPropertyTypeForSetter((Class) object, name); } else if (object instanceof Map) { Map map = (Map) object; Object value = map.get(name); if (value == null) { type = Object.class; } else { type = value.getClass(); } } else { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); while (parser.hasMoreTokens()) { name = parser.nextToken(); type = ClassInfo.getInstance(type).getSetterType(name); } } else { type = ClassInfo.getInstance(type).getSetterType(name); } } return type; } /** * Returns the class that the getter will return when reading a property value. * * @param object The bean to check * @param name The name of the property * @return The type of the property */ public Class getPropertyTypeForGetter(Object object, String name) { Class type = object.getClass(); if (object instanceof Class) { type = getClassPropertyTypeForGetter((Class) object, name); } else if (object instanceof Map) { Map map = (Map) object; Object value = map.get(name); if (value == null) { type = Object.class; } else { type = value.getClass(); } } else { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); while (parser.hasMoreTokens()) { name = parser.nextToken(); type = ClassInfo.getInstance(type).getGetterType(name); } } else { type = ClassInfo.getInstance(type).getGetterType(name); } } return type; } /** * Returns the class that the getter will return when reading a property value. * * @param type The class to check * @param name The name of the property * @return The type of the property */ private Class getClassPropertyTypeForGetter(Class type, String name) { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); while (parser.hasMoreTokens()) { name = parser.nextToken(); type = ClassInfo.getInstance(type).getGetterType(name); } } else { type = ClassInfo.getInstance(type).getGetterType(name); } return type; } /** * Returns the class that the setter expects to receive as a parameter when * setting a property value. * * @param type The class to check * @param name The name of the property * @return The type of the property */ private Class getClassPropertyTypeForSetter(Class type, String name) { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); while (parser.hasMoreTokens()) { name = parser.nextToken(); type = ClassInfo.getInstance(type).getSetterType(name); } } else { type = ClassInfo.getInstance(type).getSetterType(name); } return type; } /** * Gets an Object property from a bean * * @param object The bean * @param name The property name * @return The property value (as an Object) */ public Object getObject(Object object, String name) { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); Object value = object; while (parser.hasMoreTokens()) { value = getProperty(value, parser.nextToken()); if (value == null) { break; } } return value; } else { return getProperty(object, name); } } /** * Sets the value of a bean property to an Object * * @param object The bean to change * @param name The name of the property to set * @param value The new value to set */ public void setObject(Object object, String name, Object value) { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); String property = parser.nextToken(); Object child = object; while (parser.hasMoreTokens()) { Class type = getPropertyTypeForSetter(child, property); Object parent = child; child = getProperty(parent, property); if (child == null) { if (value == null) { return; // don't instantiate child path if value is null } else { try { child = ResultObjectFactoryUtil.createObjectThroughFactory(type); setObject(parent, property, child); } catch (Exception e) { throw new ProbeException("Cannot set value of property '" + name + "' because '" + property + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e); } } } property = parser.nextToken(); } setProperty(child, property, value); } else { setProperty(object, name, value); } } /** * Checks to see if a bean has a writable property be a given name * * @param object The bean to check * @param propertyName The property to check for * @return True if the property exists and is writable */ public boolean hasWritableProperty(Object object, String propertyName) { boolean hasProperty = false; if (object instanceof Map) { hasProperty = true;//((Map) object).containsKey(propertyName); } else { if (propertyName.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(propertyName, "."); Class type = object.getClass(); while (parser.hasMoreTokens()) { propertyName = parser.nextToken(); type = ClassInfo.getInstance(type).getGetterType(propertyName); hasProperty = ClassInfo.getInstance(type).hasWritableProperty(propertyName); } } else { hasProperty = ClassInfo.getInstance(object.getClass()).hasWritableProperty(propertyName); } } return hasProperty; } /** * Checks to see if a bean has a readable property be a given name * * @param object The bean to check * @param propertyName The property to check for * @return True if the property exists and is readable */ public boolean hasReadableProperty(Object object, String propertyName) { boolean hasProperty = false; if (object instanceof Map) { hasProperty = true;//((Map) object).containsKey(propertyName); } else { if (propertyName.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(propertyName, "."); Class type = object.getClass(); while (parser.hasMoreTokens()) { propertyName = parser.nextToken(); type = ClassInfo.getInstance(type).getGetterType(propertyName); hasProperty = ClassInfo.getInstance(type).hasReadableProperty(propertyName); } } else { hasProperty = ClassInfo.getInstance(object.getClass()).hasReadableProperty(propertyName); } } return hasProperty; } protected Object getProperty(Object object, String name) { try { Object value = null; if (name.indexOf('[') > -1) { value = getIndexedProperty(object, name); } else { if (object instanceof Map) { int index = name.indexOf('.'); if (index > -1) { String mapId = name.substring(0, index); value = getProperty(((Map) object).get(mapId), name.substring(index + 1)); } else { value = ((Map) object).get(name); } } else { int index = name.indexOf('.'); if (index > -1) { String newName = name.substring(0, index); value = getProperty(getObject(object, newName), name.substring(index + 1)); } else { ClassInfo classCache = ClassInfo.getInstance(object.getClass()); Invoker method = classCache.getGetInvoker(name); if (method == null) { throw new NoSuchMethodException("No GET method for property " + name + " on instance of " + object.getClass().getName()); } try { value = method.invoke(object, NO_ARGUMENTS); } catch (Throwable t) { throw ClassInfo.unwrapThrowable(t); } } } } return value; } catch (ProbeException e) { throw e; } catch (Throwable t) { if (object == null) { throw new ProbeException("Could not get property '" + name + "' from null reference. Cause: " + t.toString(), t); } else { throw new ProbeException("Could not get property '" + name + "' from " + object.getClass().getName() + ". Cause: " + t.toString(), t); } } } protected void setProperty(Object object, String name, Object value) { ClassInfo classCache = ClassInfo.getInstance(object.getClass()); try { if (name.indexOf('[') > -1) { setIndexedProperty(object, name, value); } else { if (object instanceof Map) { ((Map) object).put(name, value); } else { Invoker method = classCache.getSetInvoker(name); if (method == null) { throw new NoSuchMethodException("No SET method for property " + name + " on instance of " + object.getClass().getName()); } Object[] params = new Object[1]; params[0] = value; try { method.invoke(object, params); } catch (Throwable t) { throw ClassInfo.unwrapThrowable(t); } } } } catch (ProbeException e) { throw e; } catch (Throwable t) { if (object == null) { throw new ProbeException("Could not set property '" + name + "' to value '"+value+"' for null reference. Cause: " + t.toString(), t); } else { throw new ProbeException("Could not set property '" + name + "' to value '"+value+"' for " + object.getClass().getName() + ". Cause: " + t.toString(), t); } } } } ibatis/src/com/ibatis/common/beans/DomProbe.java0000644000175000017500000002457011047641630022053 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import org.w3c.dom.CharacterData; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import com.ibatis.common.resources.Resources; /** * A Probe implementation for working with DOM objects */ public class DomProbe extends BaseProbe { public String[] getReadablePropertyNames(Object object) { List props = new ArrayList(); Element e = resolveElement(object); NodeList nodes = e.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { props.add(nodes.item(i).getNodeName()); } return (String[]) props.toArray(new String[props.size()]); } public String[] getWriteablePropertyNames(Object object) { List props = new ArrayList(); Element e = resolveElement(object); NodeList nodes = e.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { props.add(nodes.item(i).getNodeName()); } return (String[]) props.toArray(new String[props.size()]); } public Class getPropertyTypeForSetter(Object object, String name) { Element e = findNestedNodeByName(resolveElement(object), name, false); //todo alias types, don't use exceptions like this try { return Resources.classForName(e.getAttribute("type")); } catch (ClassNotFoundException e1) { return Object.class; } } public Class getPropertyTypeForGetter(Object object, String name) { Element e = findNestedNodeByName(resolveElement(object), name, false); //todo alias types, don't use exceptions like this try { return Resources.classForName(e.getAttribute("type")); } catch (ClassNotFoundException e1) { return Object.class; } } public boolean hasWritableProperty(Object object, String propertyName) { return findNestedNodeByName(resolveElement(object), propertyName, false) != null; } public boolean hasReadableProperty(Object object, String propertyName) { return findNestedNodeByName(resolveElement(object), propertyName, false) != null; } public Object getObject(Object object, String name) { Object value = null; Element element = findNestedNodeByName(resolveElement(object), name, false); if (element != null) { value = getElementValue(element); } return value; } public void setObject(Object object, String name, Object value) { Element element = findNestedNodeByName(resolveElement(object), name, true); if (element != null) { setElementValue(element, value); } } protected void setProperty(Object object, String property, Object value) { Element element = findNodeByName(resolveElement(object), property, 0, true); if (element != null) { setElementValue(element, value); } } protected Object getProperty(Object object, String property) { Object value = null; Element element = findNodeByName(resolveElement(object), property, 0, false); if (element != null) { value = getElementValue(element); } return value; } private Element resolveElement(Object object) { Element element = null; if (object instanceof Document) { element = (Element) ((Document) object).getLastChild(); } else if (object instanceof Element) { element = (Element) object; } else { throw new ProbeException("An unknown object type was passed to DomProbe. Must be a Document."); } return element; } private void setElementValue(Element element, Object value) { CharacterData data = null; Element prop = element; if (value instanceof Collection) { Iterator items = ((Collection) value).iterator(); while (items.hasNext()) { Document valdoc = (Document) items.next(); NodeList list = valdoc.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { Node newNode = element.getOwnerDocument().importNode(list.item(i), true); element.appendChild(newNode); } } } else if (value instanceof Document) { Document valdoc = (Document) value; Node lastChild = valdoc.getLastChild(); NodeList list = lastChild.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { Node newNode = element.getOwnerDocument().importNode(list.item(i), true); element.appendChild(newNode); } } else if (value instanceof Element) { Node newNode = element.getOwnerDocument().importNode((Element) value, true); element.appendChild(newNode); } else { // Find text child element NodeList texts = prop.getChildNodes(); if (texts.getLength() == 1) { Node child = texts.item(0); if (child instanceof CharacterData) { // Use existing text. data = (CharacterData) child; } else { // Remove non-text, add text. prop.removeChild(child); Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value)); prop.appendChild(text); data = text; } } else if (texts.getLength() > 1) { // Remove all, add text. for (int i = texts.getLength() - 1; i >= 0; i--) { prop.removeChild(texts.item(i)); } Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value)); prop.appendChild(text); data = text; } else { // Add text. Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value)); prop.appendChild(text); data = text; } data.setData(String.valueOf(value)); } // Set type attribute //prop.setAttribute("type", value == null ? "null" : value.getClass().getName()); } private Object getElementValue(Element element) { StringBuffer value = null; Element prop = element; if (prop != null) { // Find text child elements NodeList texts = prop.getChildNodes(); if (texts.getLength() > 0) { value = new StringBuffer(); for (int i = 0; i < texts.getLength(); i++) { Node text = texts.item(i); if (text instanceof CharacterData) { value.append(((CharacterData) text).getData()); } } } } //convert to proper type //value = convert(value.toString()); if (value == null) { return null; } else { return String.valueOf(value); } } private Element findNestedNodeByName(Element element, String name, boolean create) { Element child = element; StringTokenizer parser = new StringTokenizer(name, ".", false); while (parser.hasMoreTokens()) { String childName = parser.nextToken(); if (childName.indexOf('[') > -1) { String propName = childName.substring(0, childName.indexOf('[')); int i = Integer.parseInt(childName.substring(childName.indexOf('[') + 1, childName.indexOf(']'))); child = findNodeByName(child, propName, i, create); } else { child = findNodeByName(child, childName, 0, create); } if (child == null) { break; } } return child; } private Element findNodeByName(Element element, String name, int index, boolean create) { Element prop = null; // Find named property element NodeList propNodes = element.getElementsByTagName(name); if (propNodes.getLength() > index) { prop = (Element) propNodes.item(index); } else { if (create) { for (int i = 0; i < index + 1; i++) { prop = element.getOwnerDocument().createElement(name); element.appendChild(prop); } } } return prop; } /** * Converts a DOM node to a complete xml string * @param node - the node to process * @param indent - how to indent the children of the node * @return The node as a String */ public static String nodeToString(Node node, String indent) { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); switch (node.getNodeType()) { case Node.DOCUMENT_NODE: printWriter.println("\n"); // recurse on each child NodeList nodes = node.getChildNodes(); if (nodes != null) { for (int i = 0; i < nodes.getLength(); i++) { printWriter.print(nodeToString(nodes.item(i), "")); } } break; case Node.ELEMENT_NODE: String name = node.getNodeName(); printWriter.print(indent + "<" + name); NamedNodeMap attributes = node.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node current = attributes.item(i); printWriter.print(" " + current.getNodeName() + "=\"" + current.getNodeValue() + "\""); } printWriter.print(">"); // recurse on each child NodeList children = node.getChildNodes(); if (children != null) { for (int i = 0; i < children.getLength(); i++) { printWriter.print(nodeToString(children.item(i), indent + indent)); } } printWriter.print(""); break; case Node.TEXT_NODE: printWriter.print(node.getNodeValue()); break; } printWriter.flush(); String result = stringWriter.getBuffer().toString(); printWriter.close(); return result; } } ibatis/src/com/ibatis/common/beans/GenericProbe.java0000644000175000017500000002210611047641630022701 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; import java.util.List; import java.util.Map; import java.util.StringTokenizer; /** * StaticBeanProbe provides methods that allow simple, reflective access to * JavaBeans style properties. Methods are provided for all simple types as * well as object types. *

* Examples: *

* StaticBeanProbe.setObject(object, propertyName, value); *

* Object value = StaticBeanProbe.getObject(object, propertyName); */ public class GenericProbe extends BaseProbe { private static final BaseProbe BEAN_PROBE = new ComplexBeanProbe(); private static final BaseProbe DOM_PROBE = new DomProbe(); protected GenericProbe() { } /** * Gets an object from a Map or bean * * @param object - the object to probe * @param name - the name of the property (or map entry) * @return The value of the property (or map entry) * @see com.ibatis.common.beans.BaseProbe#getObject(java.lang.Object, java.lang.String) */ public Object getObject(Object object, String name) { if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.getObject(object, name); } else if (object instanceof List) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof Object[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof char[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof boolean[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof byte[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof double[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof float[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof int[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof long[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else if (object instanceof short[]) { return BEAN_PROBE.getIndexedProperty(object, name); } else { return BEAN_PROBE.getObject(object, name); } } /** * Sets an object in a Map or bean * * @param object - the object to probe * @param name - the name of the property (or map entry) * @param value - the new value of the property (or map entry) * @see com.ibatis.common.beans.BaseProbe#setObject(java.lang.Object, java.lang.String, java.lang.Object) */ public void setObject(Object object, String name, Object value) { if (object instanceof org.w3c.dom.Document) { DOM_PROBE.setObject(object, name, value); } else { BEAN_PROBE.setObject(object, name, value); } } /** * Gets an array of the readable properties in a Map or JavaBean * * @param object - the object to get properties for * @return The array of properties (or map entries) * @see com.ibatis.common.beans.BaseProbe#getReadablePropertyNames(java.lang.Object) */ public String[] getReadablePropertyNames(Object object) { if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.getReadablePropertyNames(object); } else { return BEAN_PROBE.getReadablePropertyNames(object); } } /** * Gets an array of the writeable properties in a Map or JavaBean * * @param object - the object to get properties for * @return The array of properties (or map entries) * @see com.ibatis.common.beans.BaseProbe#getWriteablePropertyNames(java.lang.Object) */ public String[] getWriteablePropertyNames(Object object) { if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.getWriteablePropertyNames(object); } else { return BEAN_PROBE.getWriteablePropertyNames(object); } } /** * Returns the class that the setter expects to receive as a parameter when * setting a property value. * * @param object - The class to check * @param name - the name of the property * @return The type of the property * @see com.ibatis.common.beans.Probe#getPropertyTypeForSetter(java.lang.Object, java.lang.String) */ public Class getPropertyTypeForSetter(Object object, String name) { if (object instanceof Class) { return getClassPropertyTypeForSetter((Class) object, name); } else if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.getPropertyTypeForSetter(object, name); } else { return BEAN_PROBE.getPropertyTypeForSetter(object, name); } } /** * Returns the class that the getter will return when reading a property value. * * @param object The bean to check * @param name The name of the property * @return The type of the property * @see com.ibatis.common.beans.Probe#getPropertyTypeForGetter(java.lang.Object, java.lang.String) */ public Class getPropertyTypeForGetter(Object object, String name) { if (object instanceof Class) { return getClassPropertyTypeForGetter((Class) object, name); } else if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.getPropertyTypeForGetter(object, name); } else if (name.indexOf('[') > -1) { return BEAN_PROBE.getIndexedType(object,name); } else { return BEAN_PROBE.getPropertyTypeForGetter(object, name); } } /** * Checks to see if an object has a writable property by a given name * * @param object The bean to check * @param propertyName The property to check for * @return True if the property exists and is writable * @see com.ibatis.common.beans.Probe#hasWritableProperty(java.lang.Object, java.lang.String) */ public boolean hasWritableProperty(Object object, String propertyName) { if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.hasWritableProperty(object, propertyName); } else { return BEAN_PROBE.hasWritableProperty(object, propertyName); } } /** * Checks to see if a bean has a readable property by a given name * * @param object The bean to check * @param propertyName The property to check for * @return True if the property exists and is readable * @see com.ibatis.common.beans.Probe#hasReadableProperty(java.lang.Object, java.lang.String) */ public boolean hasReadableProperty(Object object, String propertyName) { if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.hasReadableProperty(object, propertyName); } else { return BEAN_PROBE.hasReadableProperty(object, propertyName); } } protected void setProperty(Object object, String property, Object value) { if (object instanceof org.w3c.dom.Document) { DOM_PROBE.setProperty(object, property, value); } else { BEAN_PROBE.setProperty(object, property, value); } } protected Object getProperty(Object object, String property) { if (object instanceof org.w3c.dom.Document) { return DOM_PROBE.getProperty(object, property); } else { return BEAN_PROBE.getProperty(object, property); } } private Class getClassPropertyTypeForGetter(Class type, String name) { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); while (parser.hasMoreTokens()) { name = parser.nextToken(); if (Map.class.isAssignableFrom(type)) { type = Object.class; break; } type = ClassInfo.getInstance(type).getGetterType(name); } } else { type = ClassInfo.getInstance(type).getGetterType(name); } return type; } /** * Returns the class that the setter expects to receive as a parameter when * setting a property value. * * @param type The class to check * @param name The name of the property * @return The type of the property */ private Class getClassPropertyTypeForSetter(Class type, String name) { if (name.indexOf('.') > -1) { StringTokenizer parser = new StringTokenizer(name, "."); while (parser.hasMoreTokens()) { name = parser.nextToken(); if (Map.class.isAssignableFrom(type)) { type = Object.class; break; } type = ClassInfo.getInstance(type).getSetterType(name); } } else { type = ClassInfo.getInstance(type).getSetterType(name); } return type; } } ibatis/src/com/ibatis/common/beans/GetFieldInvoker.java0000644000175000017500000000104611047641630023356 0ustar twernertwernerpackage com.ibatis.common.beans; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Field; public class GetFieldInvoker implements Invoker { private Field field; private String name; public GetFieldInvoker(Field field) { this.field = field; this.name = "(" + field.getName() + ")"; } public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException { return field.get(target); } public String getName() { return name; } } ibatis/src/com/ibatis/common/beans/Invoker.java0000644000175000017500000000037011047641630021751 0ustar twernertwernerpackage com.ibatis.common.beans; import java.lang.reflect.InvocationTargetException; public interface Invoker { String getName(); Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException; } ibatis/src/com/ibatis/common/beans/MethodInvoker.java0000644000175000017500000000114411047641630023112 0ustar twernertwernerpackage com.ibatis.common.beans; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; public class MethodInvoker implements Invoker { private Method method; private String name; public MethodInvoker(Method method) { this.method = method; this.name = method.getName(); } public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException { return method.invoke(target, args); } public Method getMethod() { return method; } public String getName() { return name; } } ibatis/src/com/ibatis/common/beans/Probe.java0000644000175000017500000000501011047641630021377 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; /** * A Probe is an object that is used to work with beans, DOM objects, or other * objects. */ public interface Probe { /** * Gets an Object property from another object * * @param object - the object * @param name - the property name * @return The property value (as an Object) */ public Object getObject(Object object, String name); /** * Sets the value of a property on an object * * @param object - the object to change * @param name - the name of the property to set * @param value - the new value to set */ public void setObject(Object object, String name, Object value); /** * Returns the class that the setter expects when setting a property * * @param object - the object to check * @param name - the name of the property * @return The type of the property */ public Class getPropertyTypeForSetter(Object object, String name); /** * Returns the class that the getter will return when reading a property * * @param object - the object to check * @param name - the name of the property * @return The type of the property */ public Class getPropertyTypeForGetter(Object object, String name); /** * Checks to see if an object has a writable property by a given name * * @param object - the object to check * @param propertyName - the property to check for * @return True if the property exists and is writable */ public boolean hasWritableProperty(Object object, String propertyName); /** * Checks to see if an object has a readable property by a given name * * @param object - the object to check * @param propertyName - the property to check for * @return True if the property exists and is readable */ public boolean hasReadableProperty(Object object, String propertyName); } ibatis/src/com/ibatis/common/beans/ProbeException.java0000644000175000017500000000300611047641630023261 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; /** * BeansException for use for by BeanProbe and StaticBeanProbe. */ public class ProbeException extends RuntimeException { /** * Default constructor */ public ProbeException() { } /** * Constructor to set the message for the exception * * @param msg - the message for the exception */ public ProbeException(String msg) { super(msg); } /** * Constructor to create a nested exception * * @param cause - the reason the exception is being thrown */ public ProbeException(Throwable cause) { super(cause); } /** * Constructor to create a nested exception with a message * * @param msg - the message for the exception * @param cause - the reason the exception is being thrown */ public ProbeException(String msg, Throwable cause) { super(msg, cause); } } ibatis/src/com/ibatis/common/beans/ProbeFactory.java0000644000175000017500000000302411047641630022732 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.beans; /** * An abstract factory for getting Probe implementations. */ public class ProbeFactory { private static final Probe DOM = new DomProbe(); private static final Probe BEAN = new ComplexBeanProbe(); private static final Probe GENERIC = new GenericProbe(); /** * Factory method for getting a Probe object * * @return An implementation of the Probe interface */ public static Probe getProbe() { return GENERIC; } /** * Factory method for getting a Probe object that is * the best choice for the type of object supplied * by the object parameter. * * @param object The object to get a Probe for * @return An implementation of the Probe interface */ public static Probe getProbe(Object object) { if (object instanceof org.w3c.dom.Document) { return DOM; } else { return BEAN; } } } ibatis/src/com/ibatis/common/beans/SetFieldInvoker.java0000644000175000017500000000107211047641630023371 0ustar twernertwernerpackage com.ibatis.common.beans; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Field; public class SetFieldInvoker implements Invoker { private Field field; private String name; public SetFieldInvoker(Field field) { this.field = field; this.name = "(" + field.getName() + ")"; } public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException { field.set(target, args[0]); return null; } public String getName() { return name; } } ibatis/src/com/ibatis/common/io/0000755000175000017500000000000011047641626017015 5ustar twernertwerneribatis/src/com/ibatis/common/io/ReaderInputStream.java0000644000175000017500000001013311047641626023254 0ustar twernertwerner/* * Java Network Programming, Second Edition * Merlin Hughes, Michael Shoffner, Derek Hamner * Manning Publications Company; ISBN 188477749X * * http://nitric.com/jnp/ * * Copyright (c) 1997-1999 Merlin Hughes, Michael Shoffner, Derek Hamner; * all rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE ABOVE NAMED AUTHORS "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS, THEIR * PUBLISHER OR THEIR EMPLOYERS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.ibatis.common.io; import java.io.*; /** * An InputStream backed by a Reader */ public class ReaderInputStream extends InputStream { protected Reader reader; protected ByteArrayOutputStream byteArrayOut; protected Writer writer; protected char[] chars; protected byte[] buffer; protected int index, length; /** * Constructor to supply a Reader * * @param reader - the Reader used by the InputStream */ public ReaderInputStream(Reader reader) { this.reader = reader; byteArrayOut = new ByteArrayOutputStream(); writer = new OutputStreamWriter(byteArrayOut); chars = new char[1024]; } /** * Constructor to supply a Reader and an encoding * * @param reader - the Reader used by the InputStream * @param encoding - the encoding to use for the InputStream * @throws UnsupportedEncodingException if the encoding is not supported */ public ReaderInputStream(Reader reader, String encoding) throws UnsupportedEncodingException { this.reader = reader; byteArrayOut = new ByteArrayOutputStream(); writer = new OutputStreamWriter(byteArrayOut, encoding); chars = new char[1024]; } /** * @see java.io.InputStream#read() */ public int read() throws IOException { if (index >= length) fillBuffer(); if (index >= length) return -1; return 0xff & buffer[index++]; } protected void fillBuffer() throws IOException { if (length < 0) return; int numChars = reader.read(chars); if (numChars < 0) { length = -1; } else { byteArrayOut.reset(); writer.write(chars, 0, numChars); writer.flush(); buffer = byteArrayOut.toByteArray(); length = buffer.length; index = 0; } } /** * @see java.io.InputStream#read(byte[], int, int) */ public int read(byte[] data, int off, int len) throws IOException { if (index >= length) fillBuffer(); if (index >= length) return -1; int amount = Math.min(len, length - index); System.arraycopy(buffer, index, data, off, amount); index += amount; return amount; } /** * @see java.io.InputStream#available() */ public int available() throws IOException { return (index < length) ? length - index : ((length >= 0) && reader.ready()) ? 1 : 0; } /** * @see java.io.InputStream#close() */ public void close() throws IOException { reader.close(); } } ibatis/src/com/ibatis/common/jdbc/0000755000175000017500000000000011047641626017310 5ustar twernertwerneribatis/src/com/ibatis/common/jdbc/exception/0000755000175000017500000000000011047641626021306 5ustar twernertwerneribatis/src/com/ibatis/common/jdbc/exception/NestedSQLException.java0000644000175000017500000000601211047641626025631 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc.exception; import java.sql.SQLException; /** * Class to allow passing an Exception with the original SQLException */ public class NestedSQLException extends SQLException { /** * Constructor from java.sql.SQLException * @see java.sql.SQLException * @param msg - the message for the exception */ public NestedSQLException(String msg) { super(msg); } /** * Constructor from java.sql.SQLException * @see java.sql.SQLException * @param reason - the reason for the exception * @param SQLState - the SQLState */ public NestedSQLException(String reason, String SQLState) { super(reason, SQLState); } /** * Constructor from java.sql.SQLException * @see java.sql.SQLException * @param reason - the reason for the exception * @param SQLState - the SQLState * @param vendorCode - a vendor supplied code to go w/ the message */ public NestedSQLException(String reason, String SQLState, int vendorCode) { super(reason, SQLState, vendorCode); } /** * Constructor from java.sql.SQLException with added nested exception * @param msg - the message for the exception * @param cause - the cause of the exception */ public NestedSQLException(String msg, Throwable cause) { super(msg); initCause(cause); } /** * Constructor from java.sql.SQLException with added nested exception * @see java.sql.SQLException * @param reason - the reason for the exception * @param SQLState - the SQLState * @param cause - the cause of the exception */ public NestedSQLException(String reason, String SQLState, Throwable cause) { super(reason, SQLState); initCause(cause); } /** * Constructor from java.sql.SQLException with added nested exception * @param reason - the reason for the exception * @param SQLState - the SQLState * @param vendorCode - a vendor supplied code to go w/ the message * @param cause - the cause of the exception */ public NestedSQLException(String reason, String SQLState, int vendorCode, Throwable cause) { super(reason, SQLState, vendorCode); initCause(cause); } /** * Constructor from java.sql.SQLException with added nested exception * @param cause - the cause of the exception */ public NestedSQLException(Throwable cause) { super(); initCause(cause); } } ibatis/src/com/ibatis/common/jdbc/exception/RuntimeSQLException.java0000644000175000017500000000526311047641626026041 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc.exception; import java.sql.SQLException; /** * Unchecked exception to allow passing an Exception with the original SQLException */ public class RuntimeSQLException extends RuntimeException { /** * Default constructor */ public RuntimeSQLException() { } /** * Constructor to pass along a message * @param msg - the message */ public RuntimeSQLException(String msg) { super(msg); } /** * Constructor to pass along another exception * @param sqlException - the exception */ public RuntimeSQLException(SQLException sqlException) { super(sqlException); } /** * Constructor to pass along a message and an exception * @param msg - the message * @param sqlException - the exception */ public RuntimeSQLException(String msg, SQLException sqlException) { super(msg, sqlException); } /** * Getter for the SQL State * @return - the state */ public String getSQLState() { Throwable cause = getCause(); if (cause instanceof SQLException) { return ((SQLException) cause).getSQLState(); } else { return null; } } /** * Getter for the error code * @return - the error code */ public int getErrorCode() { Throwable cause = getCause(); if (cause instanceof SQLException) { return ((SQLException) cause).getErrorCode(); } else { return -1; } } /** * Get the next exception in the chain * @return - the next exception */ public SQLException getNextException() { Throwable cause = getCause(); if (cause instanceof SQLException) { return ((SQLException) cause).getNextException(); } else { return null; } } /** * Set the next exception in the chain * @param ex - the next exception */ public synchronized void setNextException(SQLException ex) { Throwable cause = getCause(); if (cause instanceof SQLException) { ((SQLException) cause).setNextException(ex); } } } ibatis/src/com/ibatis/common/jdbc/logging/0000755000175000017500000000000011047641626020736 5ustar twernertwerneribatis/src/com/ibatis/common/jdbc/logging/BaseLogProxy.java0000644000175000017500000000765511047641626024174 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc.logging; import java.util.*; /** * Base class for proxies to do logging */ public class BaseLogProxy { private static int nextId = 100000; protected static final Set SET_METHODS = new HashSet(); protected static final Set GET_METHODS = new HashSet(); protected static final Set EXECUTE_METHODS = new HashSet(); private Map columnMap = new HashMap(); private List columnNames = new ArrayList(); private List columnValues = new ArrayList(); protected int id; /** * Default constructor */ public BaseLogProxy() { id = getNextId(); } static { SET_METHODS.add("setString"); SET_METHODS.add("setInt"); SET_METHODS.add("setByte"); SET_METHODS.add("setShort"); SET_METHODS.add("setLong"); SET_METHODS.add("setDouble"); SET_METHODS.add("setFloat"); SET_METHODS.add("setTimestamp"); SET_METHODS.add("setDate"); SET_METHODS.add("setTime"); SET_METHODS.add("setArray"); SET_METHODS.add("setBigDecimal"); SET_METHODS.add("setAsciiStream"); SET_METHODS.add("setBinaryStream"); SET_METHODS.add("setBlob"); SET_METHODS.add("setBoolean"); SET_METHODS.add("setBytes"); SET_METHODS.add("setCharacterStream"); SET_METHODS.add("setClob"); SET_METHODS.add("setObject"); SET_METHODS.add("setNull"); GET_METHODS.add("getString"); GET_METHODS.add("getInt"); GET_METHODS.add("getByte"); GET_METHODS.add("getShort"); GET_METHODS.add("getLong"); GET_METHODS.add("getDouble"); GET_METHODS.add("getFloat"); GET_METHODS.add("getTimestamp"); GET_METHODS.add("getDate"); GET_METHODS.add("getTime"); GET_METHODS.add("getArray"); GET_METHODS.add("getBigDecimal"); GET_METHODS.add("getAsciiStream"); GET_METHODS.add("getBinaryStream"); GET_METHODS.add("getBlob"); GET_METHODS.add("getBoolean"); GET_METHODS.add("getBytes"); GET_METHODS.add("getCharacterStream"); GET_METHODS.add("getClob"); GET_METHODS.add("getObject"); GET_METHODS.add("getNull"); EXECUTE_METHODS.add("execute"); EXECUTE_METHODS.add("executeUpdate"); EXECUTE_METHODS.add("executeQuery"); } protected void setColumn(Object key, Object value) { columnMap.put(key, value); columnNames.add(key); columnValues.add(value); } protected Object getColumn(Object key) { return columnMap.get(key); } protected String getValueString() { return columnValues.toString(); } protected String getTypeString() { List typeList = new ArrayList(columnValues.size()); for (int i = 0; i < columnValues.size(); i++) { Object value = columnValues.get(i); if (value == null) { typeList.add("null"); } else { typeList.add(value.getClass().getName()); } } return typeList.toString(); } protected String getColumnString() { return columnNames.toString(); } protected void clearColumnInfo() { columnMap.clear(); columnNames.clear(); columnValues.clear(); } protected String removeBreakingWhitespace(String original) { return original.replace('\n', ' ').replace('\r', ' ').replace('\t', ' '); } protected synchronized static int getNextId() { return nextId++; } } ibatis/src/com/ibatis/common/jdbc/logging/ConnectionLogProxy.java0000644000175000017500000000653711047641626025417 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc.logging; import com.ibatis.common.beans.ClassInfo; import com.ibatis.common.logging.Log; import com.ibatis.common.logging.LogFactory; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.Statement; /** * Connection proxy to add logging */ public class ConnectionLogProxy extends BaseLogProxy implements InvocationHandler { private static final Log log = LogFactory.getLog(Connection.class); private Connection connection; private ConnectionLogProxy(Connection conn) { super(); this.connection = conn; if (log.isDebugEnabled()) { log.debug("{conn-" + id + "} Connection"); } } public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { try { if ("prepareStatement".equals(method.getName())) { if (log.isDebugEnabled()) { log.debug("{conn-" + id + "} Preparing Statement: " + removeBreakingWhitespace((String) params[0])); } PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params); stmt = PreparedStatementLogProxy.newInstance(stmt, (String) params[0]); return stmt; } else if ("prepareCall".equals(method.getName())) { if (log.isDebugEnabled()) { log.debug("{conn-" + id + "} Preparing Call: " + removeBreakingWhitespace((String) params[0])); } PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params); stmt = PreparedStatementLogProxy.newInstance(stmt, (String) params[0]); return stmt; } else if ("createStatement".equals(method.getName())) { Statement stmt = (Statement) method.invoke(connection, params); stmt = StatementLogProxy.newInstance(stmt); return stmt; } else { return method.invoke(connection, params); } } catch (Throwable t) { Throwable t1 = ClassInfo.unwrapThrowable(t); log.error("Error calling Connection." + method.getName() + ':', t1); throw t1; } } /** * Creates a logging version of a connection * @param conn - the original connection * @return - the connection with logging */ public static Connection newInstance(Connection conn) { InvocationHandler handler = new ConnectionLogProxy(conn); ClassLoader cl = Connection.class.getClassLoader(); return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler); } /** * return the wrapped connection * * @return the connection */ public Connection getConnection() { return connection; } } ibatis/src/com/ibatis/common/jdbc/logging/PreparedStatementLogProxy.java0000644000175000017500000000765111047641626026745 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc.logging; import com.ibatis.common.beans.ClassInfo; import com.ibatis.common.logging.Log; import com.ibatis.common.logging.LogFactory; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; /** * PreparedStatement proxy to add logging */ public class PreparedStatementLogProxy extends BaseLogProxy implements InvocationHandler { private static final Log log = LogFactory.getLog(PreparedStatement.class); private PreparedStatement statement; private String sql; private PreparedStatementLogProxy(PreparedStatement stmt, String sql) { this.statement = stmt; this.sql = sql; } public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { try { if (EXECUTE_METHODS.contains(method.getName())) { if (log.isDebugEnabled()) { log.debug("{pstm-" + id + "} Executing Statement: " + removeBreakingWhitespace(sql)); log.debug("{pstm-" + id + "} Parameters: " + getValueString()); log.debug("{pstm-" + id + "} Types: " + getTypeString()); } clearColumnInfo(); if ("executeQuery".equals(method.getName())) { ResultSet rs = (ResultSet) method.invoke(statement, params); if ( rs != null ) { return ResultSetLogProxy.newInstance(rs); } else { return null; } } else { return method.invoke(statement, params); } } else if (SET_METHODS.contains(method.getName())) { if ("setNull".equals(method.getName())) { setColumn(params[0], null); } else { setColumn(params[0], params[1]); } return method.invoke(statement, params); } else if ("getResultSet".equals(method.getName())) { ResultSet rs = (ResultSet) method.invoke(statement, params); if ( rs != null ) { return ResultSetLogProxy.newInstance(rs); } else { return null; } } else if ("equals".equals(method.getName())) { Object ps = params[0]; if (ps instanceof Proxy) { return new Boolean(proxy == ps); } return new Boolean(false); } else if ("hashCode".equals(method.getName())) { return new Integer(proxy.hashCode()); } else { return method.invoke(statement, params); } } catch (Throwable t) { throw ClassInfo.unwrapThrowable(t); } } /** * Creates a logging version of a PreparedStatement * @param stmt - the statement * @param sql - the sql statement * @return - the proxy */ public static PreparedStatement newInstance(PreparedStatement stmt, String sql) { InvocationHandler handler = new PreparedStatementLogProxy(stmt, sql); ClassLoader cl = PreparedStatement.class.getClassLoader(); return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler); } /** * Return the wrapped prepared statement * @return the PreparedStatement */ public PreparedStatement getPreparedStatement() { return statement; } } ibatis/src/com/ibatis/common/jdbc/logging/ResultSetLogProxy.java0000644000175000017500000000557011047641626025246 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc.logging; import com.ibatis.common.beans.ClassInfo; import com.ibatis.common.logging.Log; import com.ibatis.common.logging.LogFactory; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.ResultSet; /** * ResultSet proxy to add logging */ public class ResultSetLogProxy extends BaseLogProxy implements InvocationHandler { private static final Log log = LogFactory.getLog(ResultSet.class); boolean first = true; private ResultSet rs; private ResultSetLogProxy(ResultSet rs) { super(); this.rs = rs; if (log.isDebugEnabled()) { log.debug("{rset-" + id + "} ResultSet"); } } public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { try { Object o = method.invoke(rs, params); if (GET_METHODS.contains(method.getName())) { if (params[0] instanceof String) { if(rs.wasNull()) { setColumn(params[0], null); } else { setColumn(params[0], o); } } } else if ("next".equals(method.getName()) || "close".equals(method.getName())) { String s = getValueString(); if (!"[]".equals(s)) { if (first) { first = false; if (log.isDebugEnabled()) { log.debug("{rset-" + id + "} Header: " + getColumnString()); } } if (log.isDebugEnabled()) { log.debug("{rset-" + id + "} Result: " + s); } } clearColumnInfo(); } return o; } catch (Throwable t) { throw ClassInfo.unwrapThrowable(t); } } /** * Creates a logging version of a ResultSet * * @param rs - the ResultSet to proxy * @return - the ResultSet with logging */ public static ResultSet newInstance(ResultSet rs) { InvocationHandler handler = new ResultSetLogProxy(rs); ClassLoader cl = ResultSet.class.getClassLoader(); return (ResultSet) Proxy.newProxyInstance(cl, new Class[]{ResultSet.class}, handler); } /** * Get the wrapped result set * @return the resultSet */ public ResultSet getRs() { return rs; } } ibatis/src/com/ibatis/common/jdbc/logging/StatementLogProxy.java0000644000175000017500000000631011047641626025251 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc.logging; import com.ibatis.common.beans.ClassInfo; import com.ibatis.common.logging.Log; import com.ibatis.common.logging.LogFactory; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.ResultSet; import java.sql.Statement; /** * Statement proxy to add logging */ public class StatementLogProxy extends BaseLogProxy implements InvocationHandler { private static final Log log = LogFactory.getLog(Statement.class); private Statement statement; private StatementLogProxy(Statement stmt) { super(); this.statement = stmt; } public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { try { if (EXECUTE_METHODS.contains(method.getName())) { if (log.isDebugEnabled()) { log.debug("{stmt-" + id + "} Statement: " + removeBreakingWhitespace((String) params[0])); } if ("executeQuery".equals(method.getName())) { ResultSet rs = (ResultSet) method.invoke(statement, params); if ( rs != null ) { return ResultSetLogProxy.newInstance(rs); } else { return null; } } else { return method.invoke(statement, params); } } else if ("getResultSet".equals(method.getName())) { ResultSet rs = (ResultSet) method.invoke(statement, params); if ( rs != null ) { return ResultSetLogProxy.newInstance(rs); } else { return null; } } else if ("equals".equals(method.getName())) { Object ps = params[0]; if (ps instanceof Proxy) { return new Boolean(proxy == ps); } return new Boolean(false); } else if ("hashCode".equals(method.getName())) { return new Integer(proxy.hashCode()); } else { return method.invoke(statement, params); } } catch (Throwable t) { throw ClassInfo.unwrapThrowable(t); } } /** * Creates a logging version of a Statement * @param stmt - the statement * @return - the proxy */ public static Statement newInstance(Statement stmt) { InvocationHandler handler = new StatementLogProxy(stmt); ClassLoader cl = Statement.class.getClassLoader(); return (Statement) Proxy.newProxyInstance(cl, new Class[]{Statement.class}, handler); } /** * return the wrapped statement * * @return the statement */ public Statement getStatement() { return statement; } } ibatis/src/com/ibatis/common/jdbc/DbcpConfiguration.java0000644000175000017500000001204111047641626023551 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc; import com.ibatis.common.beans.Probe; import com.ibatis.common.beans.ProbeFactory; import org.apache.commons.dbcp.BasicDataSource; import javax.sql.DataSource; import java.util.Iterator; import java.util.Map; /** * Wrapper class to simplify use of DBCP */ public class DbcpConfiguration { private static final Probe PROBE = ProbeFactory.getProbe(); private static final String ADD_DRIVER_PROPS_PREFIX = "Driver."; private static final int ADD_DRIVER_PROPS_PREFIX_LENGTH = ADD_DRIVER_PROPS_PREFIX.length(); private DataSource dataSource; /** * Constructor to supply a map of properties * * @param properties - the map of configuration properties */ public DbcpConfiguration(Map properties) { try { dataSource = legacyDbcpConfiguration(properties); if (dataSource == null) { dataSource = newDbcpConfiguration(properties); } } catch (Exception e) { throw new RuntimeException("Error initializing DbcpDataSourceFactory. Cause: " + e, e); } } /** * Getter for DataSource * * @return The DataSource */ public DataSource getDataSource() { return dataSource; } private BasicDataSource newDbcpConfiguration(Map map) { BasicDataSource basicDataSource = new BasicDataSource(); Iterator props = map.keySet().iterator(); while (props.hasNext()) { String propertyName = (String) props.next(); if (propertyName.startsWith(ADD_DRIVER_PROPS_PREFIX)) { String value = (String) map.get(propertyName); basicDataSource.addConnectionProperty(propertyName.substring(ADD_DRIVER_PROPS_PREFIX_LENGTH), value); } else if (PROBE.hasWritableProperty(basicDataSource, propertyName)) { String value = (String) map.get(propertyName); Object convertedValue = convertValue(basicDataSource, propertyName, value); PROBE.setObject(basicDataSource, propertyName, convertedValue); } } return basicDataSource; } private Object convertValue(Object object, String propertyName, String value) { Object convertedValue = value; Class targetType = PROBE.getPropertyTypeForSetter(object, propertyName); if (targetType == Integer.class || targetType == int.class) { convertedValue = Integer.valueOf(value); } else if (targetType == Long.class || targetType == long.class) { convertedValue = Long.valueOf(value); } else if (targetType == Boolean.class || targetType == boolean.class) { convertedValue = Boolean.valueOf(value); } return convertedValue; } private BasicDataSource legacyDbcpConfiguration(Map map) { BasicDataSource basicDataSource = null; if (map.containsKey("JDBC.Driver")) { basicDataSource = new BasicDataSource(); String driver = (String) map.get("JDBC.Driver"); String url = (String) map.get("JDBC.ConnectionURL"); String username = (String) map.get("JDBC.Username"); String password = (String) map.get("JDBC.Password"); String validationQuery = (String) map.get("Pool.ValidationQuery"); String maxActive = (String) map.get("Pool.MaximumActiveConnections"); String maxIdle = (String) map.get("Pool.MaximumIdleConnections"); String maxWait = (String) map.get("Pool.MaximumWait"); basicDataSource.setUrl(url); basicDataSource.setDriverClassName(driver); basicDataSource.setUsername(username); basicDataSource.setPassword(password); if (notEmpty(validationQuery)) { basicDataSource.setValidationQuery(validationQuery); } if (notEmpty(maxActive)) { basicDataSource.setMaxActive(Integer.parseInt(maxActive)); } if (notEmpty(maxIdle)) { basicDataSource.setMaxIdle(Integer.parseInt(maxIdle)); } if (notEmpty(maxWait)) { basicDataSource.setMaxWait(Integer.parseInt(maxWait)); } Iterator props = map.keySet().iterator(); while (props.hasNext()) { String propertyName = (String) props.next(); if (propertyName.startsWith(ADD_DRIVER_PROPS_PREFIX)) { String value = (String) map.get(propertyName); basicDataSource.addConnectionProperty(propertyName.substring(ADD_DRIVER_PROPS_PREFIX_LENGTH), value); } } } return basicDataSource; } private boolean notEmpty(String s) { return s != null && s.length() > 0; } } ibatis/src/com/ibatis/common/jdbc/ScriptRunner.java0000644000175000017500000001676511047641626022630 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc; import com.ibatis.common.resources.Resources; import java.io.IOException; import java.io.LineNumberReader; import java.io.PrintWriter; import java.io.Reader; import java.sql.*; /** * Tool to run database scripts */ public class ScriptRunner { private static final String DEFAULT_DELIMITER = ";"; 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; /** * Default constructor */ public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError) { this.connection = connection; this.autoCommit = autoCommit; this.stopOnError = stopOnError; } public void setDelimiter(String delimiter, boolean fullLineDelimiter) { this.delimiter = delimiter; this.fullLineDelimiter = fullLineDelimiter; } 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; } /** * Setter for logWriter property * * @param logWriter - the new value of the logWriter property */ public void setLogWriter(PrintWriter logWriter) { this.logWriter = logWriter; } /** * Setter for errorLogWriter property * * @param errorLogWriter - the new value of the errorLogWriter property */ public void setErrorLogWriter(PrintWriter errorLogWriter) { this.errorLogWriter = errorLogWriter; } /** * Runs an SQL script (read in using the Reader parameter) * * @param reader - the source of the script */ public void runScript(Reader reader) throws IOException, SQLException{ try { if (connection == null) { DriverManager.registerDriver((Driver) Resources.instantiate(driver)); Connection conn = DriverManager.getConnection(url, username, password); try { if (conn.getAutoCommit() != autoCommit) { conn.setAutoCommit(autoCommit); } runScript(conn, reader); } finally { conn.close(); } } else { boolean originalAutoCommit = connection.getAutoCommit(); try { if (originalAutoCommit != this.autoCommit) { connection.setAutoCommit(this.autoCommit); } runScript(connection, reader); } finally { connection.setAutoCommit(originalAutoCommit); } } } catch (IOException e) { throw e; } catch (SQLException e) { throw e; } catch (Exception e) { throw new RuntimeException("Error running script. Cause: " + e, e); } } /** * 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 SQLException if any SQL errors occur * @throws IOException if there is an error reading from the Reader */ private void runScript(Connection conn, Reader reader) throws IOException, SQLException { StringBuffer command = null; try { LineNumberReader lineReader = new LineNumberReader(reader); String line = null; 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 { 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); print(name + "\t"); } println(""); while (rs.next()) { for (int i = 0; i < cols; i++) { String value = rs.getString(i); 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(); } } } ibatis/src/com/ibatis/common/jdbc/SimpleDataSource.java0000644000175000017500000011530611047641626023365 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.jdbc; import com.ibatis.common.beans.ClassInfo; import com.ibatis.common.resources.Resources; import com.ibatis.common.logging.LogFactory; import com.ibatis.common.logging.Log; import javax.sql.DataSource; import java.io.PrintWriter; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.*; import java.util.*; /** * This is a simple, synchronous, thread-safe database connection pool. *

* REQUIRED PROPERTIES * ------------------- * JDBC.Driver * JDBC.ConnectionURL * JDBC.Username * JDBC.Password *

* Pool.MaximumActiveConnections * Pool.MaximumIdleConnections * Pool.MaximumCheckoutTime * Pool.TimeToWait * Pool.PingQuery * Pool.PingEnabled * Pool.PingConnectionsOlderThan * Pool.PingConnectionsNotUsedFor * Pool.QuietMode */ public class SimpleDataSource implements DataSource { private static final Log log = LogFactory.getLog(SimpleDataSource.class); // Required Properties private static final String PROP_JDBC_DRIVER = "JDBC.Driver"; private static final String PROP_JDBC_URL = "JDBC.ConnectionURL"; private static final String PROP_JDBC_USERNAME = "JDBC.Username"; private static final String PROP_JDBC_PASSWORD = "JDBC.Password"; private static final String PROP_JDBC_DEFAULT_AUTOCOMMIT = "JDBC.DefaultAutoCommit"; // Optional Properties private static final String PROP_POOL_MAX_ACTIVE_CONN = "Pool.MaximumActiveConnections"; private static final String PROP_POOL_MAX_IDLE_CONN = "Pool.MaximumIdleConnections"; private static final String PROP_POOL_MAX_CHECKOUT_TIME = "Pool.MaximumCheckoutTime"; private static final String PROP_POOL_TIME_TO_WAIT = "Pool.TimeToWait"; private static final String PROP_POOL_PING_QUERY = "Pool.PingQuery"; private static final String PROP_POOL_PING_CONN_OLDER_THAN = "Pool.PingConnectionsOlderThan"; private static final String PROP_POOL_PING_ENABLED = "Pool.PingEnabled"; private static final String PROP_POOL_PING_CONN_NOT_USED_FOR = "Pool.PingConnectionsNotUsedFor"; private int expectedConnectionTypeCode; // Additional Driver Properties prefix private static final String ADD_DRIVER_PROPS_PREFIX = "Driver."; private static final int ADD_DRIVER_PROPS_PREFIX_LENGTH = ADD_DRIVER_PROPS_PREFIX.length(); // ----- BEGIN: FIELDS LOCKED BY POOL_LOCK ----- private final Object POOL_LOCK = new Object(); private List idleConnections = new ArrayList(); private List activeConnections = new ArrayList(); private long requestCount = 0; private long accumulatedRequestTime = 0; private long accumulatedCheckoutTime = 0; private long claimedOverdueConnectionCount = 0; private long accumulatedCheckoutTimeOfOverdueConnections = 0; private long accumulatedWaitTime = 0; private long hadToWaitCount = 0; private long badConnectionCount = 0; // ----- END: FIELDS LOCKED BY POOL_LOCK ----- // ----- BEGIN: PROPERTY FIELDS FOR CONFIGURATION ----- private String jdbcDriver; private String jdbcUrl; private String jdbcUsername; private String jdbcPassword; private boolean jdbcDefaultAutoCommit; private Properties driverProps; private boolean useDriverProps; private int poolMaximumActiveConnections; private int poolMaximumIdleConnections; private int poolMaximumCheckoutTime; private int poolTimeToWait; private String poolPingQuery; private boolean poolPingEnabled; private int poolPingConnectionsOlderThan; private int poolPingConnectionsNotUsedFor; //----- END: PROPERTY FIELDS FOR CONFIGURATION ----- /** * Constructor to allow passing in a map of properties for configuration * * @param props - the configuration parameters */ public SimpleDataSource(Map props) { initialize(props); } private void initialize(Map props) { try { String prop_pool_ping_query = null; if (props == null) { throw new RuntimeException("SimpleDataSource: The properties map passed to the initializer was null."); } if (!(props.containsKey(PROP_JDBC_DRIVER) && props.containsKey(PROP_JDBC_URL) && props.containsKey(PROP_JDBC_USERNAME) && props.containsKey(PROP_JDBC_PASSWORD))) { throw new RuntimeException("SimpleDataSource: Some properties were not set."); } else { jdbcDriver = (String) props.get(PROP_JDBC_DRIVER); jdbcUrl = (String) props.get(PROP_JDBC_URL); jdbcUsername = (String) props.get(PROP_JDBC_USERNAME); jdbcPassword = (String) props.get(PROP_JDBC_PASSWORD); poolMaximumActiveConnections = props.containsKey(PROP_POOL_MAX_ACTIVE_CONN) ? Integer.parseInt((String) props.get(PROP_POOL_MAX_ACTIVE_CONN)) : 10; poolMaximumIdleConnections = props.containsKey(PROP_POOL_MAX_IDLE_CONN) ? Integer.parseInt((String) props.get(PROP_POOL_MAX_IDLE_CONN)) : 5; poolMaximumCheckoutTime = props.containsKey(PROP_POOL_MAX_CHECKOUT_TIME) ? Integer.parseInt((String) props.get(PROP_POOL_MAX_CHECKOUT_TIME)) : 20000; poolTimeToWait = props.containsKey(PROP_POOL_TIME_TO_WAIT) ? Integer.parseInt((String) props.get(PROP_POOL_TIME_TO_WAIT)) : 20000; poolPingEnabled = props.containsKey(PROP_POOL_PING_ENABLED) && Boolean.valueOf((String) props.get(PROP_POOL_PING_ENABLED)).booleanValue(); prop_pool_ping_query = (String) props.get(PROP_POOL_PING_QUERY); poolPingQuery = props.containsKey(PROP_POOL_PING_QUERY) ? prop_pool_ping_query : "NO PING QUERY SET"; poolPingConnectionsOlderThan = props.containsKey(PROP_POOL_PING_CONN_OLDER_THAN) ? Integer.parseInt((String) props.get(PROP_POOL_PING_CONN_OLDER_THAN)) : 0; poolPingConnectionsNotUsedFor = props.containsKey(PROP_POOL_PING_CONN_NOT_USED_FOR) ? Integer.parseInt((String) props.get(PROP_POOL_PING_CONN_NOT_USED_FOR)) : 0; jdbcDefaultAutoCommit = props.containsKey(PROP_JDBC_DEFAULT_AUTOCOMMIT) && Boolean.valueOf((String) props.get(PROP_JDBC_DEFAULT_AUTOCOMMIT)).booleanValue(); useDriverProps = false; Iterator propIter = props.keySet().iterator(); driverProps = new Properties(); driverProps.put("user", jdbcUsername); driverProps.put("password", jdbcPassword); while (propIter.hasNext()) { String name = (String) propIter.next(); String value = (String) props.get(name); if (name.startsWith(ADD_DRIVER_PROPS_PREFIX)) { driverProps.put(name.substring(ADD_DRIVER_PROPS_PREFIX_LENGTH), value); useDriverProps = true; } } expectedConnectionTypeCode = assembleConnectionTypeCode(jdbcUrl, jdbcUsername, jdbcPassword); Resources.instantiate(jdbcDriver); if ( poolPingEnabled && (!props.containsKey(PROP_POOL_PING_QUERY) || prop_pool_ping_query.trim().length() == 0) ) { throw new RuntimeException("SimpleDataSource: property '" + PROP_POOL_PING_ENABLED + "' is true, but property '" + PROP_POOL_PING_QUERY + "' is not set correctly."); } } } catch (Exception e) { log.error("SimpleDataSource: Error while loading properties. Cause: " + e.toString(), e); throw new RuntimeException("SimpleDataSource: Error while loading properties. Cause: " + e, e); } } private int assembleConnectionTypeCode(String url, String username, String password) { return ("" + url + username + password).hashCode(); } /** * @see javax.sql.DataSource#getConnection() */ public Connection getConnection() throws SQLException { return popConnection(jdbcUsername, jdbcPassword).getProxyConnection(); } /** * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) */ public Connection getConnection(String username, String password) throws SQLException { return popConnection(username, password).getProxyConnection(); } /** * @see javax.sql.DataSource#setLoginTimeout(int) */ public void setLoginTimeout(int loginTimeout) throws SQLException { DriverManager.setLoginTimeout(loginTimeout); } /** * @see javax.sql.DataSource#getLoginTimeout() */ public int getLoginTimeout() throws SQLException { return DriverManager.getLoginTimeout(); } /** * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter) */ public void setLogWriter(PrintWriter logWriter) throws SQLException { DriverManager.setLogWriter(logWriter); } /** * @see javax.sql.DataSource#getLogWriter() */ public PrintWriter getLogWriter() throws SQLException { return DriverManager.getLogWriter(); } /** * If a connection has not been used in this many milliseconds, ping the * database to make sure the connection is still good. * * @return the number of milliseconds of inactivity that will trigger a ping */ public int getPoolPingConnectionsNotUsedFor() { return poolPingConnectionsNotUsedFor; } /** * Getter for the name of the JDBC driver class used * @return The name of the class */ public String getJdbcDriver() { return jdbcDriver; } /** * Getter of the JDBC URL used * @return The JDBC URL */ public String getJdbcUrl() { return jdbcUrl; } /** * Getter for the JDBC user name used * @return The user name */ public String getJdbcUsername() { return jdbcUsername; } /** * Getter for the JDBC password used * @return The password */ public String getJdbcPassword() { return jdbcPassword; } /** * Getter for the maximum number of active connections * @return The maximum number of active connections */ public int getPoolMaximumActiveConnections() { return poolMaximumActiveConnections; } /** * Getter for the maximum number of idle connections * @return The maximum number of idle connections */ public int getPoolMaximumIdleConnections() { return poolMaximumIdleConnections; } /** * Getter for the maximum time a connection can be used before it *may* be * given away again. * @return The maximum time */ public int getPoolMaximumCheckoutTime() { return poolMaximumCheckoutTime; } /** * Getter for the time to wait before retrying to get a connection * @return The time to wait */ public int getPoolTimeToWait() { return poolTimeToWait; } /** * Getter for the query to be used to check a connection * @return The query */ public String getPoolPingQuery() { return poolPingQuery; } /** * Getter to tell if we should use the ping query * @return True if we need to check a connection before using it */ public boolean isPoolPingEnabled() { return poolPingEnabled; } /** * Getter for the age of connections that should be pinged before using * @return The age */ public int getPoolPingConnectionsOlderThan() { return poolPingConnectionsOlderThan; } private int getExpectedConnectionTypeCode() { return expectedConnectionTypeCode; } /** * Getter for the number of connection requests made * @return The number of connection requests made */ public long getRequestCount() { synchronized (POOL_LOCK) { return requestCount; } } /** * Getter for the average time required to get a connection to the database * @return The average time */ public long getAverageRequestTime() { synchronized (POOL_LOCK) { return requestCount == 0 ? 0 : accumulatedRequestTime / requestCount; } } /** * Getter for the average time spent waiting for connections that were in use * @return The average time */ public long getAverageWaitTime() { synchronized (POOL_LOCK) { return hadToWaitCount == 0 ? 0 : accumulatedWaitTime / hadToWaitCount; } } /** * Getter for the number of requests that had to wait for connections that were in use * @return The number of requests that had to wait */ public long getHadToWaitCount() { synchronized (POOL_LOCK) { return hadToWaitCount; } } /** * Getter for the number of invalid connections that were found in the pool * @return The number of invalid connections */ public long getBadConnectionCount() { synchronized (POOL_LOCK) { return badConnectionCount; } } /** * Getter for the number of connections that were claimed before they were returned * @return The number of connections */ public long getClaimedOverdueConnectionCount() { synchronized (POOL_LOCK) { return claimedOverdueConnectionCount; } } /** * Getter for the average age of overdue connections * @return The average age */ public long getAverageOverdueCheckoutTime() { synchronized (POOL_LOCK) { return claimedOverdueConnectionCount == 0 ? 0 : accumulatedCheckoutTimeOfOverdueConnections / claimedOverdueConnectionCount; } } /** * Getter for the average age of a connection checkout * @return The average age */ public long getAverageCheckoutTime() { synchronized (POOL_LOCK) { return requestCount == 0 ? 0 : accumulatedCheckoutTime / requestCount; } } /** * Returns the status of the connection pool * @return The status */ public String getStatus() { StringBuffer buffer = new StringBuffer(); buffer.append("\n==============================================================="); buffer.append("\n jdbcDriver ").append(jdbcDriver); buffer.append("\n jdbcUrl ").append(jdbcUrl); buffer.append("\n jdbcUsername ").append(jdbcUsername); buffer.append("\n jdbcPassword ").append((jdbcPassword == null ? "NULL" : "************")); buffer.append("\n poolMaxActiveConnections ").append(poolMaximumActiveConnections); buffer.append("\n poolMaxIdleConnections ").append(poolMaximumIdleConnections); buffer.append("\n poolMaxCheckoutTime " + poolMaximumCheckoutTime); buffer.append("\n poolTimeToWait " + poolTimeToWait); buffer.append("\n poolPingEnabled " + poolPingEnabled); buffer.append("\n poolPingQuery " + poolPingQuery); buffer.append("\n poolPingConnectionsOlderThan " + poolPingConnectionsOlderThan); buffer.append("\n poolPingConnectionsNotUsedFor " + poolPingConnectionsNotUsedFor); buffer.append("\n --------------------------------------------------------------"); buffer.append("\n activeConnections " + activeConnections.size()); buffer.append("\n idleConnections " + idleConnections.size()); buffer.append("\n requestCount " + getRequestCount()); buffer.append("\n averageRequestTime " + getAverageRequestTime()); buffer.append("\n averageCheckoutTime " + getAverageCheckoutTime()); buffer.append("\n claimedOverdue " + getClaimedOverdueConnectionCount()); buffer.append("\n averageOverdueCheckoutTime " + getAverageOverdueCheckoutTime()); buffer.append("\n hadToWait " + getHadToWaitCount()); buffer.append("\n averageWaitTime " + getAverageWaitTime()); buffer.append("\n badConnectionCount " + getBadConnectionCount()); buffer.append("\n==============================================================="); return buffer.toString(); } /** * Closes all of the connections in the pool */ public void forceCloseAll() { synchronized (POOL_LOCK) { for (int i = activeConnections.size(); i > 0; i--) { try { SimplePooledConnection conn = (SimplePooledConnection) activeConnections.remove(i - 1); conn.invalidate(); Connection realConn = conn.getRealConnection(); if (!realConn.getAutoCommit()) { realConn.rollback(); } realConn.close(); } catch (Exception e) { // ignore } } for (int i = idleConnections.size(); i > 0; i--) { try { SimplePooledConnection conn = (SimplePooledConnection) idleConnections.remove(i - 1); conn.invalidate(); Connection realConn = conn.getRealConnection(); if (!realConn.getAutoCommit()) { realConn.rollback(); } realConn.close(); } catch (Exception e) { // ignore } } } if (log.isDebugEnabled()) { log.debug("SimpleDataSource forcefully closed/removed all connections."); } } private void pushConnection(SimplePooledConnection conn) throws SQLException { synchronized (POOL_LOCK) { activeConnections.remove(conn); if (conn.isValid()) { if (idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == getExpectedConnectionTypeCode()) { accumulatedCheckoutTime += conn.getCheckoutTime(); if (!conn.getRealConnection().getAutoCommit()) { conn.getRealConnection().rollback(); } SimplePooledConnection newConn = new SimplePooledConnection(conn.getRealConnection(), this); idleConnections.add(newConn); newConn.setCreatedTimestamp(conn.getCreatedTimestamp()); newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp()); conn.invalidate(); if (log.isDebugEnabled()) { log.debug("Returned connection " + newConn.getRealHashCode() + " to pool."); } POOL_LOCK.notifyAll(); } else { accumulatedCheckoutTime += conn.getCheckoutTime(); if (!conn.getRealConnection().getAutoCommit()) { conn.getRealConnection().rollback(); } conn.getRealConnection().close(); if (log.isDebugEnabled()) { log.debug("Closed connection " + conn.getRealHashCode() + "."); } conn.invalidate(); } } else { if (log.isDebugEnabled()) { log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection."); } badConnectionCount++; } } } private SimplePooledConnection popConnection(String username, String password) throws SQLException { boolean countedWait = false; SimplePooledConnection conn = null; long t = System.currentTimeMillis(); int localBadConnectionCount = 0; while (conn == null) { synchronized (POOL_LOCK) { if (idleConnections.size() > 0) { // Pool has available connection conn = (SimplePooledConnection) idleConnections.remove(0); if (log.isDebugEnabled()) { log.debug("Checked out connection " + conn.getRealHashCode() + " from pool."); } } else { // Pool does not have available connection if (activeConnections.size() < poolMaximumActiveConnections) { // Can create new connection if (useDriverProps) { conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, driverProps), this); } else { conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword), this); } Connection realConn = conn.getRealConnection(); if (realConn.getAutoCommit() != jdbcDefaultAutoCommit) { realConn.setAutoCommit(jdbcDefaultAutoCommit); } if (log.isDebugEnabled()) { log.debug("Created connection " + conn.getRealHashCode() + "."); } } else { // Cannot create new connection SimplePooledConnection oldestActiveConnection = (SimplePooledConnection) activeConnections.get(0); long longestCheckoutTime = oldestActiveConnection.getCheckoutTime(); if (longestCheckoutTime > poolMaximumCheckoutTime) { // Can claim overdue connection claimedOverdueConnectionCount++; accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime; accumulatedCheckoutTime += longestCheckoutTime; activeConnections.remove(oldestActiveConnection); if (!oldestActiveConnection.getRealConnection().getAutoCommit()) { oldestActiveConnection.getRealConnection().rollback(); } conn = new SimplePooledConnection(oldestActiveConnection.getRealConnection(), this); oldestActiveConnection.invalidate(); if (log.isDebugEnabled()) { log.debug("Claimed overdue connection " + conn.getRealHashCode() + "."); } } else { // Must wait try { if (!countedWait) { hadToWaitCount++; countedWait = true; } if (log.isDebugEnabled()) { log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection."); } long wt = System.currentTimeMillis(); POOL_LOCK.wait(poolTimeToWait); accumulatedWaitTime += System.currentTimeMillis() - wt; } catch (InterruptedException e) { break; } } } } if (conn != null) { if (conn.isValid()) { if (!conn.getRealConnection().getAutoCommit()) { conn.getRealConnection().rollback(); } conn.setConnectionTypeCode(assembleConnectionTypeCode(jdbcUrl, username, password)); conn.setCheckoutTimestamp(System.currentTimeMillis()); conn.setLastUsedTimestamp(System.currentTimeMillis()); activeConnections.add(conn); requestCount++; accumulatedRequestTime += System.currentTimeMillis() - t; } else { if (log.isDebugEnabled()) { log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection."); } badConnectionCount++; localBadConnectionCount++; conn = null; if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) { if (log.isDebugEnabled()) { log.debug("SimpleDataSource: Could not get a good connection to the database."); } throw new SQLException("SimpleDataSource: Could not get a good connection to the database."); } } } } } if (conn == null) { if (log.isDebugEnabled()) { log.debug("SimpleDataSource: Unknown severe error condition. The connection pool returned a null connection."); } throw new SQLException("SimpleDataSource: Unknown severe error condition. The connection pool returned a null connection."); } return conn; } /** * Method to check to see if a connection is still usable * * @param conn - the connection to check * @return True if the connection is still usable */ private boolean pingConnection(SimplePooledConnection conn) { boolean result = true; try { result = !conn.getRealConnection().isClosed(); } catch (SQLException e) { if (log.isDebugEnabled()) { log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage()); } result = false; } if (result) { if (poolPingEnabled) { if ((poolPingConnectionsOlderThan > 0 && conn.getAge() > poolPingConnectionsOlderThan) || (poolPingConnectionsNotUsedFor > 0 && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor)) { try { if (log.isDebugEnabled()) { log.debug("Testing connection " + conn.getRealHashCode() + " ..."); } Connection realConn = conn.getRealConnection(); Statement statement = realConn.createStatement(); ResultSet rs = statement.executeQuery(poolPingQuery); rs.close(); statement.close(); if (!realConn.getAutoCommit()) { realConn.rollback(); } result = true; if (log.isDebugEnabled()) { log.debug("Connection " + conn.getRealHashCode() + " is GOOD!"); } } catch (Exception e) { log.warn("Execution of ping query '" + poolPingQuery + "' failed: " + e.getMessage()); try { conn.getRealConnection().close(); } catch (Exception e2) { //ignore } result = false; if (log.isDebugEnabled()) { log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage()); } } } } } return result; } /** * Unwraps a pooled connection to get to the 'real' connection * * @param conn - the pooled connection to unwrap * @return The 'real' connection */ public static Connection unwrapConnection(Connection conn) { if (conn instanceof SimplePooledConnection) { return ((SimplePooledConnection) conn).getRealConnection(); } else { return conn; } } protected void finalize() throws Throwable { forceCloseAll(); } /** * --------------------------------------------------------------------------------------- * SimplePooledConnection * --------------------------------------------------------------------------------------- */ public static class SimplePooledConnection implements InvocationHandler { private static final String CLOSE = "close"; private static final Class[] IFACES = new Class[]{Connection.class}; private int hashCode = 0; private SimpleDataSource dataSource; private Connection realConnection; private Connection proxyConnection; private long checkoutTimestamp; private long createdTimestamp; private long lastUsedTimestamp; private int connectionTypeCode; private boolean valid; /** * Constructor for SimplePooledConnection that uses the Connection and SimpleDataSource passed in * * @param connection - the connection that is to be presented as a pooled connection * @param dataSource - the dataSource that the connection is from */ public SimplePooledConnection(Connection connection, SimpleDataSource dataSource) { this.hashCode = connection.hashCode(); this.realConnection = connection; this.dataSource = dataSource; this.createdTimestamp = System.currentTimeMillis(); this.lastUsedTimestamp = System.currentTimeMillis(); this.valid = true; proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this); } /** * Invalidates the connection */ public void invalidate() { valid = false; } /** * Method to see if the connection is usable * * @return True if the connection is usable */ public boolean isValid() { return valid && realConnection != null && dataSource.pingConnection(this); } /** * Getter for the *real* connection that this wraps * @return The connection */ public Connection getRealConnection() { return realConnection; } /** * Getter for the proxy for the connection * @return The proxy */ public Connection getProxyConnection() { return proxyConnection; } /** * Gets the hashcode of the real connection (or 0 if it is null) * * @return The hashcode of the real connection (or 0 if it is null) */ public int getRealHashCode() { if (realConnection == null) { return 0; } else { return realConnection.hashCode(); } } /** * Getter for the connection type (based on url + user + password) * @return The connection type */ public int getConnectionTypeCode() { return connectionTypeCode; } /** * Setter for the connection type * @param connectionTypeCode - the connection type */ public void setConnectionTypeCode(int connectionTypeCode) { this.connectionTypeCode = connectionTypeCode; } /** * Getter for the time that the connection was created * @return The creation timestamp */ public long getCreatedTimestamp() { return createdTimestamp; } /** * Setter for the time that the connection was created * @param createdTimestamp - the timestamp */ public void setCreatedTimestamp(long createdTimestamp) { this.createdTimestamp = createdTimestamp; } /** * Getter for the time that the connection was last used * @return - the timestamp */ public long getLastUsedTimestamp() { return lastUsedTimestamp; } /** * Setter for the time that the connection was last used * @param lastUsedTimestamp - the timestamp */ public void setLastUsedTimestamp(long lastUsedTimestamp) { this.lastUsedTimestamp = lastUsedTimestamp; } /** * Getter for the time since this connection was last used * @return - the time since the last use */ public long getTimeElapsedSinceLastUse() { return System.currentTimeMillis() - lastUsedTimestamp; } /** * Getter for the age of the connection * @return the age */ public long getAge() { return System.currentTimeMillis() - createdTimestamp; } /** * Getter for the timestamp that this connection was checked out * @return the timestamp */ public long getCheckoutTimestamp() { return checkoutTimestamp; } /** * Setter for the timestamp that this connection was checked out * @param timestamp the timestamp */ public void setCheckoutTimestamp(long timestamp) { this.checkoutTimestamp = timestamp; } /** * Getter for the time that this connection has been checked out * @return the time */ public long getCheckoutTime() { return System.currentTimeMillis() - checkoutTimestamp; } private Connection getValidConnection() { if (!valid) { throw new RuntimeException("Error accessing SimplePooledConnection. Connection is invalid."); } return realConnection; } public int hashCode() { return hashCode; } /** * Allows comparing this connection to another * * @param obj - the other connection to test for equality * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { if (obj instanceof SimplePooledConnection) { return realConnection.hashCode() == (((SimplePooledConnection) obj).realConnection.hashCode()); } else if (obj instanceof Connection) { return hashCode == obj.hashCode(); } else { return false; } } // ********************************** // Implemented Connection Methods -- Now handled by proxy // ********************************** /** * Required for InvocationHandler implementation. * * @param proxy - not used * @param method - the method to be executed * @param args - the parameters to be passed to the method * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) { dataSource.pushConnection(this); return null; } else { try { return method.invoke(getValidConnection(), args); } catch (Throwable t) { throw ClassInfo.unwrapThrowable(t); } } } public Statement createStatement() throws SQLException { return getValidConnection().createStatement(); } public PreparedStatement prepareStatement(String sql) throws SQLException { return getValidConnection().prepareStatement(sql); } public CallableStatement prepareCall(String sql) throws SQLException { return getValidConnection().prepareCall(sql); } public String nativeSQL(String sql) throws SQLException { return getValidConnection().nativeSQL(sql); } public void setAutoCommit(boolean autoCommit) throws SQLException { getValidConnection().setAutoCommit(autoCommit); } public boolean getAutoCommit() throws SQLException { return getValidConnection().getAutoCommit(); } public void commit() throws SQLException { getValidConnection().commit(); } public void rollback() throws SQLException { getValidConnection().rollback(); } public void close() throws SQLException { dataSource.pushConnection(this); } public boolean isClosed() throws SQLException { return getValidConnection().isClosed(); } public DatabaseMetaData getMetaData() throws SQLException { return getValidConnection().getMetaData(); } public void setReadOnly(boolean readOnly) throws SQLException { getValidConnection().setReadOnly(readOnly); } public boolean isReadOnly() throws SQLException { return getValidConnection().isReadOnly(); } public void setCatalog(String catalog) throws SQLException { getValidConnection().setCatalog(catalog); } public String getCatalog() throws SQLException { return getValidConnection().getCatalog(); } public void setTransactionIsolation(int level) throws SQLException { getValidConnection().setTransactionIsolation(level); } public int getTransactionIsolation() throws SQLException { return getValidConnection().getTransactionIsolation(); } public SQLWarning getWarnings() throws SQLException { return getValidConnection().getWarnings(); } public void clearWarnings() throws SQLException { getValidConnection().clearWarnings(); } public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { return getValidConnection().createStatement(resultSetType, resultSetConcurrency); } public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency); } public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency); } public Map getTypeMap() throws SQLException { return getValidConnection().getTypeMap(); } public void setTypeMap(Map map) throws SQLException { getValidConnection().setTypeMap(map); } // ********************************** // JDK 1.4 JDBC 3.0 Methods below // ********************************** public void setHoldability(int holdability) throws SQLException { getValidConnection().setHoldability(holdability); } public int getHoldability() throws SQLException { return getValidConnection().getHoldability(); } public Savepoint setSavepoint() throws SQLException { return getValidConnection().setSavepoint(); } public Savepoint setSavepoint(String name) throws SQLException { return getValidConnection().setSavepoint(name); } public void rollback(Savepoint savepoint) throws SQLException { getValidConnection().rollback(savepoint); } public void releaseSavepoint(Savepoint savepoint) throws SQLException { getValidConnection().releaseSavepoint(savepoint); } public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return getValidConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); } public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return getValidConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return getValidConnection().prepareStatement(sql, autoGeneratedKeys); } public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException { return getValidConnection().prepareStatement(sql, columnIndexes); } public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException { return getValidConnection().prepareStatement(sql, columnNames); } } } ibatis/src/com/ibatis/common/logging/0000755000175000017500000000000011047641626020034 5ustar twernertwerneribatis/src/com/ibatis/common/logging/jakarta/0000755000175000017500000000000011047641626021451 5ustar twernertwerneribatis/src/com/ibatis/common/logging/jakarta/JakartaCommonsLoggingImpl.java0000644000175000017500000000123311047641626027355 0ustar twernertwernerpackage com.ibatis.common.logging.jakarta; import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log; public class JakartaCommonsLoggingImpl implements com.ibatis.common.logging.Log { private Log log; public JakartaCommonsLoggingImpl(Class clazz) { log = LogFactory.getLog(clazz); } public boolean isDebugEnabled() { return log.isDebugEnabled(); } public void error(String s, Throwable e) { log.error(s,e); } public void error(String s) { log.error(s); } public void debug(String s) { log.debug(s); } public void warn(String s) { log.warn(s); } } ibatis/src/com/ibatis/common/logging/jdk14/0000755000175000017500000000000011047641626020751 5ustar twernertwerneribatis/src/com/ibatis/common/logging/jdk14/Jdk14LoggingImpl.java0000644000175000017500000000134111047641626024621 0ustar twernertwernerpackage com.ibatis.common.logging.jdk14; import java.util.logging.Logger; import java.util.logging.Level; public class Jdk14LoggingImpl implements com.ibatis.common.logging.Log { private Logger log; public Jdk14LoggingImpl(Class clazz) { log = Logger.getLogger(clazz.getName()); } public boolean isDebugEnabled() { return log.isLoggable(Level.FINE); } public void error(String s, Throwable e) { log.log(Level.SEVERE, s, e); } public void error(String s) { log.log(Level.SEVERE, s); } public void debug(String s) { log.log(Level.FINE, s); } public void warn(String s) { log.log(Level.WARNING, s); } } ibatis/src/com/ibatis/common/logging/log4j/0000755000175000017500000000000011047641626021053 5ustar twernertwerneribatis/src/com/ibatis/common/logging/log4j/Log4jImpl.java0000644000175000017500000000111111047641626023511 0ustar twernertwernerpackage com.ibatis.common.logging.log4j; import org.apache.log4j.Logger; public class Log4jImpl implements com.ibatis.common.logging.Log { private Logger log; public Log4jImpl(Class clazz) { log = Logger.getLogger(clazz); } public boolean isDebugEnabled() { return log.isDebugEnabled(); } public void error(String s, Throwable e) { log.error(s, e); } public void error(String s) { log.error(s); } public void debug(String s) { log.debug(s); } public void warn(String s) { log.warn(s); } } ibatis/src/com/ibatis/common/logging/nologging/0000755000175000017500000000000011047641626022017 5ustar twernertwerneribatis/src/com/ibatis/common/logging/nologging/NoLoggingImpl.java0000644000175000017500000000064411047641626025373 0ustar twernertwernerpackage com.ibatis.common.logging.nologging; import com.ibatis.common.logging.Log; public class NoLoggingImpl implements Log { public NoLoggingImpl(Class clazz) { } public boolean isDebugEnabled() { return false; } public void error(String s, Throwable e) { } public void error(String s) { } public void debug(String s) { } public void warn(String s) { } } ibatis/src/com/ibatis/common/logging/Log.java0000644000175000017500000000035211047641626021420 0ustar twernertwernerpackage com.ibatis.common.logging; public interface Log { boolean isDebugEnabled(); void error(String s, Throwable e); void error(String s); public void debug(String s); public void warn(String s); } ibatis/src/com/ibatis/common/logging/LogFactory.java0000644000175000017500000000562011047641626022753 0ustar twernertwernerpackage com.ibatis.common.logging; import java.lang.reflect.Constructor; import com.ibatis.common.resources.Resources; public class LogFactory { private static Constructor logConstructor; static { tryImplementation("org.apache.commons.logging.LogFactory", "com.ibatis.common.logging.jakarta.JakartaCommonsLoggingImpl"); tryImplementation("org.apache.log4j.Logger", "com.ibatis.common.logging.log4j.Log4jImpl"); tryImplementation("java.util.logging.Logger", "com.ibatis.common.logging.jdk14.Jdk14LoggingImpl"); tryImplementation("java.lang.Object", "com.ibatis.common.logging.nologging.NoLoggingImpl"); } private static void tryImplementation(String testClassName, String implClassName) { if (logConstructor == null) { try { Resources.classForName(testClassName); Class implClass = Resources.classForName(implClassName); logConstructor = implClass.getConstructor(new Class[]{Class.class}); } catch (Throwable t) { } } } public static Log getLog(Class aClass) { try { return (Log)logConstructor.newInstance(new Object[]{aClass}); } catch (Throwable t) { throw new RuntimeException("Error creating logger for class " + aClass + ". Cause: " + t, t); } } /** * This method will switch the logging implementation to Log4J if * Log4J is available on the classpath. This is useful in situations * where you want to use Log4J to log iBATIS activity but * commons logging is on the classpath. Note that this method is only * effective for log classes obtained after calling this method. If you * intend to use this method you should call it before calling any other * iBATIS method. * */ public static synchronized void selectLog4JLogging() { try { Resources.classForName("org.apache.log4j.Logger"); Class implClass = Resources.classForName("com.ibatis.common.logging.log4j.Log4jImpl"); logConstructor = implClass.getConstructor(new Class[]{Class.class}); } catch (Throwable t) { } } /** * This method will switch the logging implementation to Java native logging if * you are running in JRE 1.4 or above. This is useful in situations * where you want to use Java native logging to log iBATIS activity but * commons logging or Log4J is on the classpath. Note that this method is only * effective for log classes obtained after calling this method. If you * intend to use this method you should call it before calling any other * iBATIS method. */ public static synchronized void selectJavaLogging() { try { Resources.classForName("java.util.logging.Logger"); Class implClass = Resources.classForName("com.ibatis.common.logging.jdk14.Jdk14LoggingImpl"); logConstructor = implClass.getConstructor(new Class[]{Class.class}); } catch (Throwable t) { } } } ibatis/src/com/ibatis/common/resources/0000755000175000017500000000000011047641630020413 5ustar twernertwerneribatis/src/com/ibatis/common/resources/Resources.java0000644000175000017500000002466711047641630023247 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.resources; import com.ibatis.common.beans.ClassInfo; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; import java.util.Properties; /** * A class to simplify access to resources through the classloader. */ public class Resources extends Object { private static ClassLoader defaultClassLoader; /** * Charset to use when calling getResourceAsReader. * null means use the system default. */ private static Charset charset; private Resources() { } /** * Returns the default classloader (may be null). * * @return The default classloader */ public static ClassLoader getDefaultClassLoader() { return defaultClassLoader; } /** * Sets the default classloader * * @param defaultClassLoader - the new default ClassLoader */ public static void setDefaultClassLoader(ClassLoader defaultClassLoader) { Resources.defaultClassLoader = defaultClassLoader; } /** * Returns the URL of the resource on the classpath * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static URL getResourceURL(String resource) throws IOException { return getResourceURL(getClassLoader(), resource); } /** * Returns the URL of the resource on the classpath * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static URL getResourceURL(ClassLoader loader, String resource) throws IOException { URL url = null; if (loader != null) url = loader.getResource(resource); if (url == null) url = ClassLoader.getSystemResource(resource); if (url == null) throw new IOException("Could not find resource " + resource); return url; } /** * Returns a resource on the classpath as a Stream object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static InputStream getResourceAsStream(String resource) throws IOException { return getResourceAsStream(getClassLoader(), resource); } /** * Returns a resource on the classpath as a Stream object * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException { InputStream in = null; if (loader != null) in = loader.getResourceAsStream(resource); if (in == null) in = ClassLoader.getSystemResourceAsStream(resource); if (in == null) throw new IOException("Could not find resource " + resource); return in; } /** * Returns a resource on the classpath as a Properties object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Properties getResourceAsProperties(String resource) throws IOException { Properties props = new Properties(); InputStream in = null; String propfile = resource; in = getResourceAsStream(propfile); props.load(in); in.close(); return props; } /** * Returns a resource on the classpath as a Properties object * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Properties getResourceAsProperties(ClassLoader loader, String resource) throws IOException { Properties props = new Properties(); InputStream in = null; String propfile = resource; in = getResourceAsStream(loader, propfile); props.load(in); in.close(); return props; } /** * Returns a resource on the classpath as a Reader object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Reader getResourceAsReader(String resource) throws IOException { Reader reader; if (charset == null) { reader = new InputStreamReader(getResourceAsStream(resource)); } else { reader = new InputStreamReader(getResourceAsStream(resource), charset); } return reader; } /** * Returns a resource on the classpath as a Reader object * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Reader getResourceAsReader(ClassLoader loader, String resource) throws IOException { Reader reader; if (charset == null) { reader = new InputStreamReader(getResourceAsStream(loader, resource)); } else { reader = new InputStreamReader(getResourceAsStream(loader, resource), charset); } return reader; } /** * Returns a resource on the classpath as a File object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static File getResourceAsFile(String resource) throws IOException { return new File(getResourceURL(resource).getFile()); } /** * Returns a resource on the classpath as a File object * * @param loader - the classloader used to load the resource * @param resource - the resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static File getResourceAsFile(ClassLoader loader, String resource) throws IOException { return new File(getResourceURL(loader, resource).getFile()); } /** * Gets a URL as an input stream * * @param urlString - the URL to get * @return An input stream with the data from the URL * @throws IOException If the resource cannot be found or read */ public static InputStream getUrlAsStream(String urlString) throws IOException { URL url = new URL(urlString); URLConnection conn = url.openConnection(); return conn.getInputStream(); } /** * Gets a URL as a Reader * * @param urlString - the URL to get * @return A Reader with the data from the URL * @throws IOException If the resource cannot be found or read */ public static Reader getUrlAsReader(String urlString) throws IOException { return new InputStreamReader(getUrlAsStream(urlString)); } /** * Gets a URL as a Properties object * * @param urlString - the URL to get * @return A Properties object with the data from the URL * @throws IOException If the resource cannot be found or read */ public static Properties getUrlAsProperties(String urlString) throws IOException { Properties props = new Properties(); InputStream in = null; String propfile = urlString; in = getUrlAsStream(propfile); props.load(in); in.close(); return props; } /** * Loads a class * * @param className - the class to load * @return The loaded class * @throws ClassNotFoundException If the class cannot be found (duh!) */ public static Class classForName(String className) throws ClassNotFoundException { Class clazz = null; try { clazz = getClassLoader().loadClass(className); } catch (Exception e) { // Ignore. Failsafe below. } if (clazz == null) { clazz = Class.forName(className); } return clazz; } /** * Creates an instance of a class * * @param className - the class to create * @return An instance of the class * @throws ClassNotFoundException If the class cannot be found (duh!) * @throws InstantiationException If the class cannot be instantiaed * @throws IllegalAccessException If the class is not public, or other access problems arise */ public static Object instantiate(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException { return instantiate(classForName(className)); } /** * Creates an instance of a class * * @param clazz - the class to create * @return An instance of the class * @throws InstantiationException If the class cannot be instantiaed * @throws IllegalAccessException If the class is not public, or other access problems arise */ public static Object instantiate(Class clazz) throws InstantiationException, IllegalAccessException { try { return ClassInfo.getInstance(clazz).instantiateClass(); } catch (Exception e) { // Try alternative...theoretically should fail for the exact same // reason, but in case of a weird security manager, this will help // some cases. //return clazz.newInstance(); return clazz.newInstance(); } } private static ClassLoader getClassLoader() { if (defaultClassLoader != null) { return defaultClassLoader; } else { return Thread.currentThread().getContextClassLoader(); } } public static Charset getCharset() { return charset; } /** * Use this method to set the Charset to be used when * calling the getResourceAsReader methods. This will * allow iBATIS to function properly when the system default * encoding doesn't deal well with unicode (IBATIS-340, IBATIS-349) * * @param charset */ public static void setCharset(Charset charset) { Resources.charset = charset; } } ibatis/src/com/ibatis/common/util/0000755000175000017500000000000011047641630017356 5ustar twernertwerneribatis/src/com/ibatis/common/util/PaginatedArrayList.java0000644000175000017500000001312611047641630023753 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.util; import java.util.*; /** * Implementation of PaginatedList backed by an ArrayList * @deprecated All paginated list features have been deprecated */ public class PaginatedArrayList implements PaginatedList { private static final ArrayList EMPTY_LIST = new ArrayList(0); private List list; private List page; private int pageSize; private int index; /** * @param pageSize */ public PaginatedArrayList(int pageSize) { this.pageSize = pageSize; this.index = 0; this.list = new ArrayList(); repaginate(); } /** * Constructor to set the initial size and the page size * @param initialCapacity - the initial size * @param pageSize - the page size */ public PaginatedArrayList(int initialCapacity, int pageSize) { this.pageSize = pageSize; this.index = 0; this.list = new ArrayList(initialCapacity); repaginate(); } /** * Constructor to create an instance using an existing collection * @param c - the collection to build the instance with * @param pageSize - the page size */ public PaginatedArrayList(Collection c, int pageSize) { this.pageSize = pageSize; this.index = 0; this.list = new ArrayList(c); repaginate(); } private void repaginate() { if (list.isEmpty()) { page = EMPTY_LIST; } else { int start = index * pageSize; int end = start + pageSize - 1; if (end >= list.size()) { end = list.size() - 1; } if (start >= list.size()) { index = 0; repaginate(); } else if (start < 0) { index = list.size() / pageSize; if (list.size() % pageSize == 0) { index--; } repaginate(); } else { page = list.subList(start, end + 1); } } } /* List accessors (uses page) */ public int size() { return page.size(); } public boolean isEmpty() { return page.isEmpty(); } public boolean contains(Object o) { return page.contains(o); } public Iterator iterator() { return page.iterator(); } public Object[] toArray() { return page.toArray(); } public Object[] toArray(Object a[]) { return page.toArray(a); } public boolean containsAll(Collection c) { return page.containsAll(c); } public Object get(int index) { return page.get(index); } public int indexOf(Object o) { return page.indexOf(o); } public int lastIndexOf(Object o) { return page.lastIndexOf(o); } public ListIterator listIterator() { return page.listIterator(); } public ListIterator listIterator(int index) { return page.listIterator(index); } public List subList(int fromIndex, int toIndex) { return page.subList(fromIndex, toIndex); } /* List mutators (uses master list) */ public boolean add(Object o) { boolean b = list.add(o); repaginate(); return b; } public boolean remove(Object o) { boolean b = list.remove(o); repaginate(); return b; } public boolean addAll(Collection c) { boolean b = list.addAll(c); repaginate(); return b; } public boolean addAll(int index, Collection c) { boolean b = list.addAll(index, c); repaginate(); return b; } public boolean removeAll(Collection c) { boolean b = list.removeAll(c); repaginate(); return b; } public boolean retainAll(Collection c) { boolean b = list.retainAll(c); repaginate(); return b; } public void clear() { list.clear(); repaginate(); } public Object set(int index, Object element) { Object o = list.set(index, element); repaginate(); return o; } public void add(int index, Object element) { list.add(index, element); repaginate(); } public Object remove(int index) { Object o = list.remove(index); repaginate(); return o; } /* Paginated List methods */ public int getPageSize() { return pageSize; } public boolean isFirstPage() { return index == 0; } public boolean isMiddlePage() { return !(isFirstPage() || isLastPage()); } public boolean isLastPage() { return list.size() - ((index + 1) * pageSize) < 1; } public boolean isNextPageAvailable() { return !isLastPage(); } public boolean isPreviousPageAvailable() { return !isFirstPage(); } public boolean nextPage() { if (isNextPageAvailable()) { index++; repaginate(); return true; } else { return false; } } public boolean previousPage() { if (isPreviousPageAvailable()) { index--; repaginate(); return true; } else { return false; } } public void gotoPage(int pageNumber) { index = pageNumber; repaginate(); } public int getPageIndex() { return index; } } ibatis/src/com/ibatis/common/util/PaginatedList.java0000644000175000017500000000576411047641630022765 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.common.util; import java.util.List; /** * Interface for lists that support paging * @deprecated All paginated list features have been deprecated */ public interface PaginatedList extends List { /** * Returns the maximum number of items per page * * @return The maximum number of items per page. */ public int getPageSize(); /** * Is the current page the first page? * * @return True if the current page is the first page or if only * a single page exists. */ public boolean isFirstPage(); /** * Is the current page a middle page (ie not first or last)? * * @return True if the current page is not the first or last page, * and more than one page exists (always returns false if only a * single page exists). */ public boolean isMiddlePage(); /** * Is the current page the last page? * * @return True if the current page is the last page or if only * a single page exists. */ public boolean isLastPage(); /** * Is a page available after the current page? * * @return True if the next page is available */ public boolean isNextPageAvailable(); /** * Is a page available before the current page? * * @return True if the previous page is available */ public boolean isPreviousPageAvailable(); /** * Moves to the next page after the current page. If the current * page is the last page, wrap to the first page. * * @return True if the page changed */ public boolean nextPage(); /** * Moves to the page before the current page. If the current * page is the first page, wrap to the last page. * * @return True if the page changed */ public boolean previousPage(); /** * Moves to a specified page. If the specified * page is beyond the last page, wrap to the first page. * If the specified page is before the first page, wrap * to the last page. * * @param pageNumber The page to go to */ public void gotoPage(int pageNumber); /** * Returns the current page index, which is a zero based integer. * All paginated list implementations should know what index they are * on, even if they don't know the ultimate boundaries (min/max). * * @return The current page */ public int getPageIndex(); } ibatis/src/com/ibatis/common/xml/0000755000175000017500000000000011047641626017206 5ustar twernertwerneribatis/src/com/ibatis/common/xml/Nodelet.java0000644000175000017500000000203311047641626021441 0ustar twernertwernerpackage com.ibatis.common.xml; import org.w3c.dom.Node; /** * A nodelet is a sort of callback or event handler that can be registered * to handle an XPath event registered with the NodeParser. */ public interface Nodelet { /** * For a registered XPath, the NodeletParser will call the Nodelet's * process method for processing. * * @param node The node represents any XML node that can be registered under * an XPath supported by the NodeletParser. Possible nodes are: *

* */ void process (Node node) throws Exception; } ibatis/src/com/ibatis/common/xml/NodeletException.java0000644000175000017500000000056411047641626023327 0ustar twernertwernerpackage com.ibatis.common.xml; public class NodeletException extends Exception { public NodeletException() { super(); } public NodeletException(String msg) { super(msg); } public NodeletException(Throwable cause) { super(cause); } public NodeletException(String msg, Throwable cause) { super(msg, cause); } } ibatis/src/com/ibatis/common/xml/NodeletParser.java0000644000175000017500000001606311047641626022626 0ustar twernertwernerpackage com.ibatis.common.xml; import org.w3c.dom.*; import org.xml.sax.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.*; /** * The NodeletParser is a callback based parser similar to SAX. The big * difference is that rather than having a single callback for all nodes, * the NodeletParser has a number of callbacks mapped to * various nodes. The callback is called a Nodelet and it is registered * with the NodeletParser against a specific XPath. */ public class NodeletParser { private Map letMap = new HashMap(); private boolean validation; private EntityResolver entityResolver; /** * Registers a nodelet for the specified XPath. Current XPaths supported * are: * */ public void addNodelet(String xpath, Nodelet nodelet) { letMap.put(xpath, nodelet); } /** * Begins parsing from the provided Reader. */ public void parse(Reader reader) throws NodeletException { try { Document doc = createDocument(reader); parse(doc.getLastChild()); } catch (Exception e) { throw new NodeletException("Error parsing XML. Cause: " + e, e); } } public void parse(InputStream inputStream) throws NodeletException { try { Document doc = createDocument(inputStream); parse(doc.getLastChild()); } catch (Exception e) { throw new NodeletException("Error parsing XML. Cause: " + e, e); } } /** * Begins parsing from the provided Node. */ public void parse(Node node) { Path path = new Path(); processNodelet(node, "/"); process(node, path); } /** * A recursive method that walkes the DOM tree, registers XPaths and * calls Nodelets registered under those XPaths. */ private void process(Node node, Path path) { if (node instanceof Element) { // Element String elementName = node.getNodeName(); path.add(elementName); processNodelet(node, path.toString()); processNodelet(node, new StringBuffer("//").append(elementName).toString()); // Attribute NamedNodeMap attributes = node.getAttributes(); int n = attributes.getLength(); for (int i = 0; i < n; i++) { Node att = attributes.item(i); String attrName = att.getNodeName(); path.add("@" + attrName); processNodelet(att, path.toString()); processNodelet(node, new StringBuffer("//@").append(attrName).toString()); path.remove(); } // Children NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { process(children.item(i), path); } path.add("end()"); processNodelet(node, path.toString()); path.remove(); path.remove(); } else if (node instanceof Text) { // Text path.add("text()"); processNodelet(node, path.toString()); processNodelet(node, "//text()"); path.remove(); } } private void processNodelet(Node node, String pathString) { Nodelet nodelet = (Nodelet) letMap.get(pathString); if (nodelet != null) { try { nodelet.process(node); } catch (Exception e) { throw new RuntimeException("Error parsing XPath '" + pathString + "'. Cause: " + e, e); } } } /** * Creates a JAXP Document from a reader. */ private Document createDocument(Reader reader) throws ParserConfigurationException, FactoryConfigurationError, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(validation); factory.setNamespaceAware(false); factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(false); factory.setCoalescing(false); factory.setExpandEntityReferences(true); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(entityResolver); builder.setErrorHandler(new ErrorHandler() { public void error(SAXParseException exception) throws SAXException { throw exception; } public void fatalError(SAXParseException exception) throws SAXException { throw exception; } public void warning(SAXParseException exception) throws SAXException { } }); return builder.parse(new InputSource(reader)); } /** * Creates a JAXP Document from an InoutStream. */ private Document createDocument(InputStream inputStream) throws ParserConfigurationException, FactoryConfigurationError, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(validation); factory.setNamespaceAware(false); factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(false); factory.setCoalescing(false); factory.setExpandEntityReferences(true); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(entityResolver); builder.setErrorHandler(new ErrorHandler() { public void error(SAXParseException exception) throws SAXException { throw exception; } public void fatalError(SAXParseException exception) throws SAXException { throw exception; } public void warning(SAXParseException exception) throws SAXException { } }); return builder.parse(new InputSource(inputStream)); } public void setValidation(boolean validation) { this.validation = validation; } public void setEntityResolver(EntityResolver resolver) { this.entityResolver = resolver; } /** * Inner helper class that assists with building XPath paths. *

* Note: Currently this is a bit slow and could be optimized. */ private static class Path { private List nodeList = new ArrayList(); public Path() { } public Path(String path) { StringTokenizer parser = new StringTokenizer(path, "/", false); while (parser.hasMoreTokens()) { nodeList.add(parser.nextToken()); } } public void add(String node) { nodeList.add(node); } public void remove() { nodeList.remove(nodeList.size() - 1); } public String toString() { StringBuffer buffer = new StringBuffer("/"); for (int i = 0; i < nodeList.size(); i++) { buffer.append(nodeList.get(i)); if (i < nodeList.size() - 1) { buffer.append("/"); } } return buffer.toString(); } } }ibatis/src/com/ibatis/common/xml/NodeletUtils.java0000644000175000017500000000412311047641626022464 0ustar twernertwernerpackage com.ibatis.common.xml; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import java.util.Properties; public class NodeletUtils { public static boolean getBooleanAttribute(Properties attribs, String name, boolean def) { String value = attribs.getProperty(name); if (value == null) { return def; } else { return "true".equals(value); } } public static int getIntAttribute(Properties attribs, String name, int def) { String value = attribs.getProperty(name); if (value == null) { return def; } else { return Integer.parseInt(value); } } public static Properties parseAttributes(Node n) { return parseAttributes(n, null); } public static Properties parseAttributes(Node n, Properties variables) { Properties attributes = new Properties(); NamedNodeMap attributeNodes = n.getAttributes(); for (int i = 0; i < attributeNodes.getLength(); i++) { Node attribute = attributeNodes.item(i); String value = parsePropertyTokens(attribute.getNodeValue(), variables); attributes.put(attribute.getNodeName(), value); } return attributes; } public static String parsePropertyTokens(String string, Properties variables) { final String OPEN = "${"; final String CLOSE = "}"; String newString = string; if (newString != null && variables != null) { int start = newString.indexOf(OPEN); int end = newString.indexOf(CLOSE); while (start > -1 && end > start) { String prepend = newString.substring(0, start); String append = newString.substring(end + CLOSE.length()); String propName = newString.substring(start + OPEN.length(), end); String propValue = variables.getProperty(propName); if (propValue == null) { newString = prepend + propName + append; } else { newString = prepend + propValue + append; } start = newString.indexOf(OPEN); end = newString.indexOf(CLOSE); } } return newString; } } ibatis/src/com/ibatis/sqlmap/0000755000175000017500000000000011047641640016407 5ustar twernertwerneribatis/src/com/ibatis/sqlmap/client/0000755000175000017500000000000011047641640017665 5ustar twernertwerneribatis/src/com/ibatis/sqlmap/client/event/0000755000175000017500000000000011047641640021006 5ustar twernertwerneribatis/src/com/ibatis/sqlmap/client/event/package.html0000644000175000017500000000012311047641640023263 0ustar twernertwerner This package contains event handler interfaces. ibatis/src/com/ibatis/sqlmap/client/event/RowHandler.java0000644000175000017500000000306311047641640023720 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.sqlmap.client.event; /** * Event handler for row by row processing. *

* The RowHandler interface is used by the SqlMapSession.queryWithRowHandler() method. * Generally a RowHandler implementation will perform some row-by-row processing logic * in cases where there are too many rows to efficiently load into memory. *

* Example: *

 * sqlMap.queryWithRowHandler ("findAllEmployees", null, new MyRowHandler()));
 * 
*/ public interface RowHandler { /** * Handles a single row of a result set. *

* This method will be called for each row in a result set. For each row the result map * will be applied to build the value object, which is then passed in as the valueObject * parameter. * * @param valueObject The object representing a single row from the query. * @see com.ibatis.sqlmap.client.SqlMapSession */ void handleRow(Object valueObject); } ibatis/src/com/ibatis/sqlmap/client/extensions/0000755000175000017500000000000011047641640022064 5ustar twernertwerneribatis/src/com/ibatis/sqlmap/client/extensions/ParameterSetter.java0000644000175000017500000002235511047641640026045 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.sqlmap.client.extensions; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; import java.sql.*; import java.util.Calendar; /** * Allows parameters to be set on the underlying prepared statement. * TypeHandlerCallback implementations use this interface to * process values before they are set on the prepared statement. * Each of these methods has a corresponding method on the * PreparedStatement class, the only difference being * that there is no need to specify the parameter index with these * methods. *

* NOTE: There is no need to implement this. The implementation * will be passed into the TypeHandlerCallback automatically. */ public interface ParameterSetter { /** * Set an array on the underlying prepared statement * @param x - the array to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setArray(Array x) throws SQLException; /** * Set an InputStream on the underlying prepared statement * @param x - the InputStream * @param length - the length of the InputStream * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setAsciiStream(InputStream x, int length) throws SQLException; /** * Set an on the underlying prepared statement * @param x * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setBigDecimal(BigDecimal x) throws SQLException; /** * Set an InputStream on the underlying prepared statement * @param x - the InputStream * @param length - the length of the InputStream * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setBinaryStream(InputStream x, int length) throws SQLException; /** * Set a blob on the underlying prepared statement * @param x - the blob * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setBlob(Blob x) throws SQLException; /** * Set a boolean on the underlying prepared statement * @param x - the boolean * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setBoolean(boolean x) throws SQLException; /** * Set a byte on the underlying prepared statement * @param x - the byte * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setByte(byte x) throws SQLException; /** * Set a byte array on the underlying prepared statement * @param x - the byte[] * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setBytes(byte x[]) throws SQLException; /** * Set a character stream on the underlying prepared statement * @param reader - the reader * @param length - the length of the reader * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setCharacterStream(Reader reader, int length) throws SQLException; /** * Set a clob on the underlying prepared statement * @param x - the clob * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setClob(Clob x) throws SQLException; /** * Set a date on the underlying prepared statement * @param x - the date * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setDate(Date x) throws SQLException; /** * Set a date with a calendar on the underlying prepared statement * @param x - the date * @param cal - the calendar * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setDate(Date x, Calendar cal) throws SQLException; /** * Set a double on the underlying prepared statement * @param x - the double * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setDouble(double x) throws SQLException; /** * Set a float on the underlying prepared statement * @param x the float * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setFloat(float x) throws SQLException; /** * Set an integer on the underlying prepared statement * @param x - the int * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setInt(int x) throws SQLException; /** * Set a long on the underlying prepared statement * @param x - the long * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setLong(long x) throws SQLException; /** * Set a null on the underlying prepared statement * @param sqlType - the type for the null value * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setNull(int sqlType) throws SQLException; /** * Set a null on the underlying prepared statement * @param sqlType - the type for the null value * @param typeName - the name of the type * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setNull(int sqlType, String typeName) throws SQLException; /** * Set an object on the underlying prepared statement * @param x - the object to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setObject(Object x) throws SQLException; /** * Set an object on the underlying prepared statement * @param x - the object to set * @param targetSqlType - the sql type of the object * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setObject(Object x, int targetSqlType) throws SQLException; /** * Set an object on the underlying prepared statement * @param x - the object to set * @param targetSqlType - the sql type of the object * @param scale - the scale of the object * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setObject(Object x, int targetSqlType, int scale) throws SQLException; /** * Set a reference on the underlying prepared statement * @param x - the reference to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setRef(Ref x) throws SQLException; /** * Set a short on the underlying prepared statement * @param x - the short to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setShort(short x) throws SQLException; /** * Set a string on the underlying prepared statement * @param x - the string to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setString(String x) throws SQLException; /** * Set a time on the underlying prepared statement * @param x - the time to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setTime(Time x) throws SQLException; /** * Set a time with a calendar on the underlying prepared statement * @param x - the time to set * @param cal - the calendar to use * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setTime(Time x, Calendar cal) throws SQLException; /** * Set a timestamp on the underlying prepared statement * @param x - the timestamp to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setTimestamp(Timestamp x) throws SQLException; /** * Set a timestamp on the underlying prepared statement * @param x - the timestamp to set * @param cal - the calendar to use * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setTimestamp(Timestamp x, Calendar cal) throws SQLException; /** * Set a URL on the underlying prepared statement * @param x - the url to set * @throws SQLException - thrown if the underlying prepared statement throws it */ public void setURL(URL x) throws SQLException; /** * Returns the underlying prepared statement...be careful! */ public PreparedStatement getPreparedStatement(); /** * Returns the index of the parameter being set. * * @return the parameter index used to set the value in the underlying * PreparedStatement */ public int getParameterIndex(); } ibatis/src/com/ibatis/sqlmap/client/extensions/ResultGetter.java0000644000175000017500000001666611047641640025377 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.sqlmap.client.extensions; import java.math.BigDecimal; import java.net.URL; import java.sql.*; import java.util.Calendar; import java.util.Map; /** * Allows values to be retrieved from the underlying result set. * TypeHandlerCallback implementations use this interface to * get values that they can subsequently manipulate before * having them returned. Each of these methods has a corresponding * method on the ResultSet (or CallableStatement) class, the only * difference being that there is no need to specify the column name * or index with these methods. *

* NOTE: There is no need to implement this. The implementation * will be passed into the TypeHandlerCallback automatically. */ public interface ResultGetter { /** * Gets an array from the underlying result set * @return - the array * @throws SQLException - if the underlying result set throws an exception */ public Array getArray() throws SQLException; /** * Gets a BigDecimal from the underlying result set * @return - the BigDecimal * @throws SQLException - if the underlying result set throws an exception */ public BigDecimal getBigDecimal() throws SQLException; /** * Gets a Blob from the underlying result set * @return - the Blob * @throws SQLException - if the underlying result set throws an exception */ public Blob getBlob() throws SQLException; /** * Gets a boolean from the underlying result set * @return - the boolean * @throws SQLException - if the underlying result set throws an exception */ public boolean getBoolean() throws SQLException; /** * Gets a byte from the underlying result set * @return - the byte * @throws SQLException - if the underlying result set throws an exception */ public byte getByte() throws SQLException; /** * Gets a byte[] from the underlying result set * @return - the byte[] * @throws SQLException - if the underlying result set throws an exception */ public byte[] getBytes() throws SQLException; /** * Gets a Clob from the underlying result set * @return - the Clob * @throws SQLException - if the underlying result set throws an exception */ public Clob getClob() throws SQLException; /** * Gets a Date from the underlying result set * @return - the Date * @throws SQLException - if the underlying result set throws an exception */ public Date getDate() throws SQLException; /** * Gets a Date from the underlying result set using a calendar * @param cal - the Calendar * @return - the Date * @throws SQLException - if the underlying result set throws an exception */ public Date getDate(Calendar cal) throws SQLException; /** * Gets a double from the underlying result set * @return - the double * @throws SQLException - if the underlying result set throws an exception */ public double getDouble() throws SQLException; /** * Gets a float from the underlying result set * @return - the float * @throws SQLException - if the underlying result set throws an exception */ public float getFloat() throws SQLException; /** * Gets an int from the underlying result set * @return - the int * @throws SQLException - if the underlying result set throws an exception */ public int getInt() throws SQLException; /** * Gets a long from the underlying result set * @return - the long * @throws SQLException - if the underlying result set throws an exception */ public long getLong() throws SQLException; /** * Gets an Object from the underlying result set * @return - the Object * @throws SQLException - if the underlying result set throws an exception */ public Object getObject() throws SQLException; /** * Gets an Object from the underlying result set using a Map * @param map - the Map * @return - the Object * @throws SQLException - if the underlying result set throws an exception */ public Object getObject(Map map) throws SQLException; /** * Gets a Ref from the underlying result set * @return - the Ref * @throws SQLException - if the underlying result set throws an exception */ public Ref getRef() throws SQLException; /** * Gets a short from the underlying result set * @return - the short * @throws SQLException - if the underlying result set throws an exception */ public short getShort() throws SQLException; /** * Gets a String from the underlying result set * @return - the String * @throws SQLException - if the underlying result set throws an exception */ public String getString() throws SQLException; /** * Gets a Time from the underlying result set * @return - the Time * @throws SQLException - if the underlying result set throws an exception */ public Time getTime() throws SQLException; /** * Gets a Time from the underlying result set using a Calendar * @param cal - the Calendar * @return - the Time * @throws SQLException - if the underlying result set throws an exception */ public Time getTime(Calendar cal) throws SQLException; /** * Gets a Timestamp from the underlying result set * @return - the Timestamp * @throws SQLException - if the underlying result set throws an exception */ public Timestamp getTimestamp() throws SQLException; /** * Gets a Timestamp from the underlying result set * @param cal - the Calendar * @return - the Timestamp * @throws SQLException - if the underlying result set throws an exception */ public Timestamp getTimestamp(Calendar cal) throws SQLException; /** * Gets a URL from the underlying result set * @return - the URL * @throws SQLException - if the underlying result set throws an exception */ public URL getURL() throws SQLException; /** * Tells if the field was null * @return - true if it was null * @throws SQLException - if the underlying result set throws an exception */ public boolean wasNull() throws SQLException; /** * Returns the underlying ResultSet...be careful! * @return a ResultSet instance. */ public ResultSet getResultSet(); /** * Returns the name of the column being got in the underlying ResultSet. * May be null in which case the getColumnIndex * method should be used. * * @return the column name (may be null) */ public String getColumnName(); /** * Returns the index of the column being got in the underlying ResultSet. * Only use this method if the value returned from getColumnName * is null. * * @return the index of the column (if zero then use the column name) */ public int getColumnIndex(); } ibatis/src/com/ibatis/sqlmap/client/extensions/TypeHandlerCallback.java0000644000175000017500000001046511047641640026571 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.sqlmap.client.extensions; import java.sql.SQLException; /** * A simple interface for implementing custom type handlers. *

* Using this interface, you can implement a type handler that * will perform customized processing before parameters are set * on a PreparedStatement and after values are retrieved from * a ResultSet. Using a custom type handler you can extend * the framework to handle types that are not supported, or * handle supported types in a different way. For example, * you might use a custom type handler to implement proprietary * BLOB support (e.g. Oracle), or you might use it to handle * booleans using "Y" and "N" instead of the more typical 0/1. *

* EXAMPLE *

Here's a simple example of a boolean handler that uses "Yes" and "No".

*
 * public class YesNoBoolTypeHandlerCallback implements TypeHandlerCallback {
 * 

* private static final String YES = "Yes"; * private static final String NO = "No"; *

* public Object getResult(ResultGetter getter) throws SQLException { * String s = getter.getString(); * if (YES.equalsIgnoreCase(s)) { * return new Boolean (true); * } else if (NO.equalsIgnoreCase(s)) { * return new Boolean (false); * } else { * throw new SQLException ("Unexpected value " + s + " found where "+YES+" or "+NO+" was expected."); * } * } *

* public void setParameter(ParameterSetter setter, Object parameter) throws SQLException { * boolean b = ((Boolean)parameter).booleanValue(); * if (b) { * setter.setString(YES); * } else { * setter.setString(NO); * } * } *

* public Object valueOf(String s) { * if (YES.equalsIgnoreCase(s)) { * return new Boolean (true); * } else if (NO.equalsIgnoreCase(s)) { * return new Boolean (false); * } else { * throw new SQLException ("Unexpected value " + s + " found where "+YES+" or "+NO+" was expected."); * } * } *

* } *

*/ public interface TypeHandlerCallback { /** * Performs processing on a value before it is used to set * the parameter of a PreparedStatement. * * @param setter The interface for setting the value on the PreparedStatement. * @param parameter The value to be set. * @throws SQLException If any error occurs. */ public void setParameter(ParameterSetter setter, Object parameter) throws SQLException; /** * Performs processing on a value before after it has been retrieved * from a ResultSet. * * @param getter The interface for getting the value from the ResultSet. * @return The processed value. * @throws SQLException If any error occurs. */ public Object getResult(ResultGetter getter) throws SQLException; /** * Casts the string representation of a value into a type recognized by * this type handler. This method is used to translate nullValue values * into types that can be appropriately compared. If your custom type handler * cannot support nullValues, or if there is no reasonable string representation * for this type (e.g. File type), you can simply return the String representation * as it was passed in. It is not recommended to return null, unless null was passed * in. * * @param s A string representation of a valid value for this type. * @return One of the following: *
    *
  1. the casted repersentation of the String value,
  2. *
  3. the string as is,
  4. *
  5. null, only if null was passed in.
  6. *
*/ public Object valueOf(String s); } ibatis/src/com/ibatis/sqlmap/client/package.html0000644000175000017500000000013211047641640022142 0ustar twernertwerner This package contains the core library client interface. ibatis/src/com/ibatis/sqlmap/client/SqlMapClient.java0000644000175000017500000002214511047641640023070 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.sqlmap.client; import java.sql.Connection; /** * A thread safe client for working with your SQL Maps (Start Here). This interface inherits transaction control * and execution methods from the SqlMapTransactionManager and SqlMapExecutor interfaces. *

* The SqlMapClient is the central class for working with SQL Maps. This class will allow you * to run mapped statements (select, insert, update, delete etc.), and also demarcate * transactions and work with batches. Once you have an SqlMapClient instance, everything * you need to work with SQL Maps is easily available. *

* The SqlMapClient can either * be worked with directly as a multi-threaded client (internal session management), or you can get a single threaded * session and work with that. There may be a slight performance increase if you explicitly * get a session (using the openSession() method), as it saves the SqlMapClient from having * to manage threads contexts. But for most cases it won't make much of a difference, so * choose whichever paradigm suits your needs or preferences. *

* An SqlMapClient instance can be safely made static or applied as a Singleton. * Generally it's a good idea to make a simple configuration class that will configure the * instance (using SqlMapClientBuilder) and provide access to it. *

* The following example will demonstrate the use of SqlMapClient. *

 * 
 * //
 * // autocommit simple query --these are just examples...not patterns
 * //
 * 
 * Employee emp = (Employee) sqlMap.queryForObject("getEmployee", new Integer(1));
 * 
 * //
 * // transaction --these are just examples...not patterns
 * //
 * 
 * try {
 *   sqlMap.startTransaction()
 *   Employee emp2 = new Employee();
 *   // ...set emp2 data
 *   Integer generatedKey = (Integer) sqlMap.insert ("insertEmployee", emp2);
 *   emp2.setFavouriteColour ("green");
 *   sqlMap.update("updateEmployee", emp2);
 *   sqlMap.commitTransaction();
 * } finally {
 *   sqlMap.endTransaction();
 * }
 * 
 * //
 * // session --these are just examples...not patterns
 * //
 * 
 * try {
 *   SqlMapSession session = sqlMap.openSession()
 *   session.startTransaction()
 *   Employee emp2 = new Employee();
 *   // ...set emp2 data
 *   Integer generatedKey = (Integer) session.insert ("insertEmployee", emp2);
 *   emp2.setFavouriteColour ("green");
 *   session.update("updateEmployee", emp2);
 *   session.commitTransaction();
 * } finally {
 *   try {
 *     session.endTransaction();
 *   } finally {
 *     session.close();
 *   }
 *   // Generally your session scope would be in a wider context and therefore the
 *   // ugly nested finally block above would not be there.  Realize that sessions
 *   // MUST be closed if explicitly opened (via openSession()).
 * }
 * 
 * //
 * // batch --these are just examples...not patterns
 * //
 * 
 * try {
 *   sqlMap.startTransaction()
 *   List list = (Employee) sqlMap.queryForList("getFiredEmployees", null);
 *   sqlMap.startBatch ();
 *   for (int i=0, n=list.size(); i < n; i++) {
 *     sqlMap.delete ("deleteEmployee", list.get(i));
 *   }
 *   sqlMap.executeBatch();
 *   sqlMap.commitTransaction();
 * } finally {
 *   sqlMap.endTransaction();
 * }
 * 
* * @see SqlMapClientBuilder * @see SqlMapSession * @see SqlMapExecutor */ public interface SqlMapClient extends SqlMapExecutor, SqlMapTransactionManager { /** * Returns a single threaded SqlMapSession implementation for use by * one user. Remember though, that SqlMapClient itself is a thread safe SqlMapSession * implementation, so you can also just work directly with it. If you do get a session * explicitly using this method be sure to close it! You can close a session using * the sqlMapSession.close() method. *

* * @return An SqlMapSession instance. */ public SqlMapSession openSession(); /** * Returns a single threaded SqlMapSession implementation for use by * one user. Remember though, that SqlMapClient itself is a thread safe SqlMapSession * implementation, so you can also just work directly with it. If you do get a session * explicitly using this method be sure to close it! You can close a session using * the SqlMapSession.close() method. *

* This particular implementation takes a user provided connection as a parameter. This * connection will be used for executing statements, and therefore overrides any * configured datasources. Using this approach allows the developer to easily use an externally * supplied connection for executing statements. *

* Important: Using a user supplied connection basically sidesteps the datasource * so you are responsible for appropriately handling your connection lifecycle (i.e. closing). * Here's a (very) simple example (throws SQLException): *

   * try {
   *   Connection connection = dataSource.getConnection();
   *   SqlMapSession session = sqlMap.openSession(connection);
   *   // do work
   *   connection.commit();
   * } catch (SQLException e) {
   *     try {
   *       if (connection != null) commit.rollback();
   *     } catch (SQLException ignored) {
   *       // generally ignored
   *     }
   *     throw e;  // rethrow the exception
   * } finally {
   *   try {
   *     if (connection != null) connection.close();
   *   } catch (SQLException ignored) {
   *     // generally ignored
   *   }
   * }
   * 
* * @param conn - the connection to use for the session * * @return An SqlMapSession instance. */ public SqlMapSession openSession(Connection conn); /** * TODO : Deprecated and will be removed. * * @return A session (DEPRECATED) * @deprecated Use openSession() instead. THIS METHOD WILL BE REMOVED BEFORE * FINAL RELEASE. */ public SqlMapSession getSession(); /** * Flushes all data caches. */ public void flushDataCache(); /** * Flushes the data cache that matches the cache model ID provided. * cacheId should include the namespace, even when * useStatementNamespaces="false". * * @param cacheId The cache model to flush */ public void flushDataCache(String cacheId); /** * Returns a generated implementation of a cusom mapper class as specified by the method * parameter. The generated implementation will run mapped statements by matching the method * name to the statement name. The mapped statement elements determine how the statement is * run as per the following: * * * How select statements are run is determined by the method signature, * as per the following: * * * How stored procedures are run is determined by the method name, * as per the following: * * * @param iface The interface that contains methods representing the mapped statements contained. * @return An instance of iface that can be used to call mapped statements directly in a typesafe * manner. */ //public Object getMapper(Class iface); }ibatis/src/com/ibatis/sqlmap/client/SqlMapClientBuilder.java0000644000175000017500000001016511047641640024376 0ustar twernertwerner/* * Copyright 2004 Clinton Begin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ibatis.sqlmap.client; import com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser; import java.io.InputStream; import java.io.Reader; import java.util.Properties; /** * Builds SqlMapClient instances from a supplied resource (e.g. XML configuration file) *

* The SqlMapClientBuilder class is responsible for parsing configuration documents * and building the SqlMapClient instance. Its current implementation works with * XML configuration files (e.g. sql-map-config.xml). *

* Example: *

 * Reader reader = Resources.getResourceAsReader("properties/sql-map-config.xml");
 * SqlMapClient client = SqlMapClientBuilder.buildSqlMapClient (reader);
 * 
*

* Examples of the XML document structure used by SqlMapClientBuilder can * be found at the links below. *

* Note: They might look big, but they're mostly comments! *