You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by cb...@apache.org on 2007/02/11 05:33:00 UTC
svn commit: r505832 - in /ibatis/trunk/java/mapper/mapper2: build/
src/com/ibatis/common/beans/ src/com/ibatis/common/jdbc/
src/com/ibatis/common/resources/ src/com/ibatis/sqlmap/engine/builder/xml/
src/com/ibatis/sqlmap/engine/mapping/parameter/ test/...
Author: cbegin
Date: Sat Feb 10 20:32:59 2007
New Revision: 505832
URL: http://svn.apache.org/viewvc?view=rev&rev=505832
Log:
1) Implemented private constructor access.
2) Centralized all calls to Class.newInstance() within ClassInfo
Added:
ibatis/trunk/java/mapper/mapper2/test/testdomain/PrivateAccount.java
Modified:
ibatis/trunk/java/mapper/mapper2/build/version.properties
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ClassInfo.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/jdbc/ScriptRunner.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/resources/Resources.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapConfigParser.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapParser.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/parameter/InlineParameterMapParser.java
ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/BaseSqlMapTest.java
ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/DirectFieldMappingTest.java
ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/Account.xml
Modified: ibatis/trunk/java/mapper/mapper2/build/version.properties
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/build/version.properties?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/build/version.properties (original)
+++ ibatis/trunk/java/mapper/mapper2/build/version.properties Sat Feb 10 20:32:59 2007
@@ -1,5 +1,5 @@
#Build version info
-#Fri Feb 09 00:34:05 MST 2007
+#Sat Feb 10 18:39:04 MST 2007
version=2.3.1
-buildDate=2007/02/09 00\:34
-buildNum=680
+buildDate=2007/02/10 18\:39
+buildNum=681
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ClassInfo.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ClassInfo.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ClassInfo.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ClassInfo.java Sat Feb 10 20:32:59 2007
@@ -43,6 +43,7 @@
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);
@@ -76,20 +77,49 @@
private ClassInfo(Class clazz) {
className = clazz.getName();
+ addDefaultConstructor(clazz);
addMethods(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 addFields(Class clazz) {
Field[] fields = clazz.getDeclaredFields();
for (int i=0; i < fields.length; i++) {
- fields[i].setAccessible(true);
- setMethods.put("(" + fields[i].getName() + ")", new SetFieldInvoker(fields[i]));
- setTypes.put("(" + fields[i].getName() + ")", fields[i].getType());
- getMethods.put("(" + fields[i].getName() + ")", new GetFieldInvoker(fields[i]));
- getTypes.put("(" + fields[i].getName() + ")", fields[i].getType());
+ 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()) {
+ setMethods.put("(" + field.getName() + ")", new SetFieldInvoker(field));
+ setTypes.put("(" + field.getName() + ")", field.getType());
+ getMethods.put("(" + field.getName() + ")", new GetFieldInvoker(field));
+ getTypes.put("(" + field.getName() + ")", field.getType());
+ }
}
if (clazz.getSuperclass() != null) {
addFields(clazz.getSuperclass());
@@ -99,29 +129,30 @@
private void addMethods(Class cls) {
Method[] methods = getAllMethodsForClass(cls);
for (int i = 0; i < methods.length; i++) {
- String name = methods[i].getName();
+ Method method = methods[i];
+ String name = method.getName();
if (name.startsWith("set") && name.length() > 3) {
- if (methods[i].getParameterTypes().length == 1) {
+ if (method.getParameterTypes().length == 1) {
name = dropCase(name);
if (setMethods.containsKey(name)) {
// TODO(JGB) - this should probably be a RuntimeException at some point???
log.error("Illegal overloaded setter method for property " + name + " in class " + cls.getName() +
". This breaks the JavaBeans specification and can cause unpredicatble results.");
}
- setMethods.put(name, new MethodInvoker(methods[i]));
- setTypes.put(name, methods[i].getParameterTypes()[0]);
+ setMethods.put(name, new MethodInvoker(method));
+ setTypes.put(name, method.getParameterTypes()[0]);
}
} else if (name.startsWith("get") && name.length() > 3) {
- if (methods[i].getParameterTypes().length == 0) {
+ if (method.getParameterTypes().length == 0) {
name = dropCase(name);
- getMethods.put(name, new MethodInvoker(methods[i]));
- getTypes.put(name, methods[i].getReturnType());
+ getMethods.put(name, new MethodInvoker(method));
+ getTypes.put(name, method.getReturnType());
}
} else if (name.startsWith("is") && name.length() > 2) {
- if (methods[i].getParameterTypes().length == 0) {
+ if (method.getParameterTypes().length == 0) {
name = dropCase(name);
- getMethods.put(name, new MethodInvoker(methods[i]));
- getTypes.put(name, methods[i].getReturnType());
+ getMethods.put(name, new MethodInvoker(method));
+ getTypes.put(name, method.getReturnType());
}
}
name = null;
@@ -147,8 +178,8 @@
* We use this method, instead of the simpler Class.getMethods(),
* because we want to look for private methods as well.
*
- * @param cls
- * @return
+ * @param cls The class
+ * @return An array containing all methods in this class
*/
private Method[] getClassMethods(Class cls) {
HashMap uniqueMethods = new HashMap();
@@ -209,17 +240,6 @@
return sb.toString();
}
- private boolean canAccessPrivateMethods() {
- try {
- System.getSecurityManager().checkPermission(new ReflectPermission("suppressAccessChecks"));
- return true;
- } catch (SecurityException e) {
- return false;
- } catch (NullPointerException e) {
- return true;
- }
- }
-
private static String dropCase(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
@@ -236,6 +256,19 @@
return name;
}
+ private static boolean canAccessPrivateMethods() {
+ try {
+ System.getSecurityManager().checkPermission(new ReflectPermission("suppressAccessChecks"));
+ return true;
+ } catch (SecurityException e) {
+ return false;
+ } catch (NullPointerException e) {
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
/**
* Gets the name of the class the instance provides information for
*
@@ -245,6 +278,18 @@
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
*
@@ -394,12 +439,12 @@
public static ClassInfo getInstance(Class clazz) {
if (cacheEnabled) {
synchronized (clazz) {
- ClassInfo cache = (ClassInfo) CLASS_INFO_MAP.get(clazz);
- if (cache == null) {
- cache = new ClassInfo(clazz);
- CLASS_INFO_MAP.put(clazz, cache);
+ ClassInfo cached = (ClassInfo) CLASS_INFO_MAP.get(clazz);
+ if (cached == null) {
+ cached = new ClassInfo(clazz);
+ CLASS_INFO_MAP.put(clazz, cached);
}
- return cache;
+ return cached;
}
} else {
return new ClassInfo(clazz);
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/jdbc/ScriptRunner.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/jdbc/ScriptRunner.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/jdbc/ScriptRunner.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/jdbc/ScriptRunner.java Sat Feb 10 20:32:59 2007
@@ -88,7 +88,7 @@
public void runScript(Reader reader) throws IOException, SQLException{
try {
if (connection == null) {
- DriverManager.registerDriver((Driver) Resources.classForName(driver).newInstance());
+ DriverManager.registerDriver((Driver) Resources.instantiate(driver));
Connection conn = DriverManager.getConnection(url, username, password);
try {
if (conn.getAutoCommit() != autoCommit) {
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/resources/Resources.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/resources/Resources.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/resources/Resources.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/resources/Resources.java Sat Feb 10 20:32:59 2007
@@ -15,6 +15,8 @@
*/
package com.ibatis.common.resources;
+import com.ibatis.common.beans.ClassInfo;
+
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
@@ -289,9 +291,16 @@
* @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 {
- return clazz.newInstance();
+ 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() {
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapConfigParser.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapConfigParser.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapConfigParser.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapConfigParser.java Sat Feb 10 20:32:59 2007
@@ -261,7 +261,7 @@
vars.errorCtx.setMoreInfo("Check the callback attribute '" + callback + "' (must be a classname).");
TypeHandler typeHandler;
- Object impl = Resources.classForName(callback).newInstance();
+ Object impl = Resources.instantiate(callback);
if (impl instanceof TypeHandlerCallback) {
typeHandler = new CustomTypeHandler((TypeHandlerCallback) impl);
} else if (impl instanceof TypeHandler) {
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapParser.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapParser.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapParser.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapParser.java Sat Feb 10 20:32:59 2007
@@ -268,7 +268,7 @@
if (callback != null) {
vars.errorCtx.setMoreInfo("Check the parameter mapping typeHandler attribute '" + callback + "' (must be a TypeHandler or TypeHandlerCallback implementation).");
try {
- Object impl = Resources.classForName(callback).newInstance();
+ Object impl = Resources.instantiate(callback);
if (impl instanceof TypeHandlerCallback) {
handler = new CustomTypeHandler((TypeHandlerCallback) impl);
} else if (impl instanceof TypeHandler) {
@@ -434,7 +434,7 @@
if (callback != null) {
vars.errorCtx.setMoreInfo("Check the result mapping typeHandler attribute '" + callback + "' (must be a TypeHandler or TypeHandlerCallback implementation).");
try {
- Object impl = Resources.classForName(callback).newInstance();
+ Object impl = Resources.instantiate(callback);
if (impl instanceof TypeHandlerCallback) {
handler = new CustomTypeHandler((TypeHandlerCallback) impl);
} else if (impl instanceof TypeHandler) {
@@ -512,7 +512,7 @@
if (callback != null) {
vars.errorCtx.setMoreInfo("Check the result mapping typeHandler attribute '" + callback + "' (must be a TypeHandlerCallback implementation).");
try {
- Object impl = Resources.classForName(callback).newInstance();
+ Object impl = Resources.instantiate(callback);
if (impl instanceof TypeHandlerCallback) {
handler = new CustomTypeHandler((TypeHandlerCallback) impl);
} else if (impl instanceof TypeHandler) {
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/parameter/InlineParameterMapParser.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/parameter/InlineParameterMapParser.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/parameter/InlineParameterMapParser.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/parameter/InlineParameterMapParser.java Sat Feb 10 20:32:59 2007
@@ -101,7 +101,7 @@
} else if ("handler".equals(field)) {
try {
value = typeHandlerFactory.resolveAlias(value);
- Object impl = Resources.classForName(value).newInstance();
+ Object impl = Resources.instantiate(value);
if (impl instanceof TypeHandlerCallback) {
mapping.setTypeHandler(new CustomTypeHandler((TypeHandlerCallback) impl));
} else if (impl instanceof TypeHandler) {
Modified: ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/BaseSqlMapTest.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/BaseSqlMapTest.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/BaseSqlMapTest.java (original)
+++ ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/BaseSqlMapTest.java Sat Feb 10 20:32:59 2007
@@ -7,6 +7,7 @@
import junit.framework.TestCase;
import testdomain.Account;
import testdomain.Order;
+import testdomain.PrivateAccount;
import javax.sql.DataSource;
import java.io.Reader;
@@ -75,7 +76,14 @@
assertEquals("Begin", account.getLastName());
assertNull(account.getEmailAddress());
}
-
+
+ protected void assertPrivateAccount6(PrivateAccount account) {
+ assertEquals(6, account.getId());
+ assertEquals("Jennifer", account.getFirstName());
+ assertEquals("Begin", account.getLastName());
+ assertNull(account.getEmailAddress());
+ }
+
protected void assertAccount1(Map account) {
Integer id = (Integer) account.get("id");
String firstName = (String) account.get("firstName");
Modified: ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/DirectFieldMappingTest.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/DirectFieldMappingTest.java?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/DirectFieldMappingTest.java (original)
+++ ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/DirectFieldMappingTest.java Sat Feb 10 20:32:59 2007
@@ -1,6 +1,7 @@
package com.ibatis.sqlmap;
import testdomain.Account;
+import testdomain.PrivateAccount;
import java.sql.SQLException;
@@ -14,7 +15,7 @@
public void testInsertAndSelectDirectToFields() throws SQLException {
Account account = newAccount6();
- sqlMap.update("insertAccountFromFields", account);
+ sqlMap.insert("insertAccountFromFields", account);
account = (Account) sqlMap.queryForObject("getAccountToFields", new Integer(6));
@@ -22,5 +23,15 @@
assertAccount6(account.getAccount());
}
+ public void testGetAccountWithPrivateConstructor() throws SQLException {
+ Account account = newAccount6();
+
+ sqlMap.insert("insertAccountFromFields", account);
+
+ PrivateAccount pvt = (PrivateAccount) sqlMap.queryForObject("getAccountWithPrivateConstructor", new Integer(6));
+
+ assertPrivateAccount6(pvt);
+ }
+
}
Modified: ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/Account.xml
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/Account.xml?view=diff&rev=505832&r1=505831&r2=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/Account.xml (original)
+++ ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/Account.xml Sat Feb 10 20:32:59 2007
@@ -493,4 +493,20 @@
where ACC_ID = #value#
</select>
+ <select id="getAccountWithPrivateConstructor"
+ parameterClass="int"
+ resultClass="testdomain.PrivateAccount">
+ select
+ ACC_ID as "(id)",
+ ACC_FIRST_NAME as "(firstName)",
+ ACC_LAST_NAME as "(lastName)",
+ ACC_EMAIL as "(emailAddress)",
+ ACC_ID as "(account).(id)",
+ ACC_FIRST_NAME as "(account).(firstName)",
+ ACC_LAST_NAME as "(account).(lastName)",
+ ACC_EMAIL as "(account).(emailAddress)"
+ from ACCOUNT
+ where ACC_ID = #value#
+ </select>
+
</sqlMap>
Added: ibatis/trunk/java/mapper/mapper2/test/testdomain/PrivateAccount.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/test/testdomain/PrivateAccount.java?view=auto&rev=505832
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/test/testdomain/PrivateAccount.java (added)
+++ ibatis/trunk/java/mapper/mapper2/test/testdomain/PrivateAccount.java Sat Feb 10 20:32:59 2007
@@ -0,0 +1,124 @@
+package testdomain;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+public class PrivateAccount implements Serializable {
+
+ private int id;
+ private String firstName;
+ private String lastName;
+ private String emailAddress;
+ private int[] ids;
+ private int age;
+ private Date dateAdded;
+ private PrivateAccount account;
+ private List accountList;
+ private boolean bannerOption;
+ private boolean cartOption;
+
+ private PrivateAccount() {
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int[] getIds() {
+ return ids;
+ }
+
+ public void setIds(int[] ids) {
+ this.ids = ids;
+ }
+
+ /**
+ * @return Returns the age.
+ */
+ public int getAge() {
+ return age;
+ }
+
+ /**
+ * @param age The age to set.
+ */
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ /**
+ * @return Returns the dateAdded.
+ */
+ public Date getDateAdded() {
+ return dateAdded;
+ }
+
+ /**
+ * @param dateAdded The dateAdded to set.
+ */
+ public void setDateAdded(Date dateAdded) {
+ this.dateAdded = dateAdded;
+ }
+
+ 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;
+ }
+
+ public PrivateAccount getAccount() {
+ return account;
+ }
+
+ public void setAccount(PrivateAccount account) {
+ this.account = account;
+ }
+
+ public List getAccountList() {
+ return accountList;
+ }
+
+ public void setAccountList(List accountList) {
+ this.accountList = accountList;
+ }
+
+ public boolean isBannerOption() {
+ return bannerOption;
+ }
+
+ public void setBannerOption(boolean bannerOption) {
+ this.bannerOption = bannerOption;
+ }
+
+
+ public boolean isCartOption() {
+ return cartOption;
+ }
+
+ public void setCartOption(boolean cartOption) {
+ this.cartOption = cartOption;
+ }
+}