Sync with 3.1.x

* 3.1.x:
  Demonstrate use of @Configuration as meta-annotation
  Prune dead code from JmsTransactionManager#doBegin
  Apply @Configuration BeanNameGenerator consistently
  Improve @Configuration bean name discovery
  Fix infinite recursion bug in nested @Configuration
  Polish static imports
  Minor fix in ServletResponseMethodArgumentResolver
  extracted ResourceUtils.useCachesIfNecessary(URLConnection) method (SP
  prepared for 3.1.1 release
  CustomSQLExceptionTranslatorRegistry/Registrar etc
  revised CustomSQLExceptionTranslatorRegistry/Registrar method naming
  use custom InputStream traversal instead of a full byte array (SPR-911
  PathMatchingResourcePatternResolver preserves caching for JNLP jar con
  Resource "contentLength()" implementations work with OSGi bundle resou
  fixed MethodInvokingJobDetailFactoryBean for compatibility with Quartz
  fixed MethodInvokingJobDetailFactoryBean for compatibility with Quartz
This commit is contained in:
Chris Beams
2012-02-16 13:00:28 +01:00
41 changed files with 622 additions and 227 deletions

View File

@@ -16,53 +16,42 @@
package org.springframework.jdbc.support;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* Registry for registering custom {@link org.springframework.jdbc.support.SQLExceptionTranslator}.
* Registry for registering custom {@link org.springframework.jdbc.support.SQLExceptionTranslator}
* instances for specific databases.
*
* @author Thomas Risberg
* @since 3.1
* @since 3.1.1
*/
public class CustomSQLExceptionTranslatorRegistrar implements InitializingBean {
private static final Log logger = LogFactory.getLog(CustomSQLExceptionTranslatorRegistrar.class);
/**
* Map registry to hold custom translators specific databases.
* Key is the database product name as defined in the
* {@link org.springframework.jdbc.support.SQLErrorCodesFactory}.
*/
private final Map<String, SQLExceptionTranslator> sqlExceptionTranslators =
new HashMap<String, SQLExceptionTranslator>();
private final Map<String, SQLExceptionTranslator> translators = new HashMap<String, SQLExceptionTranslator>();
/**
* Setter for a Map of translators where the key must be the database name as defined in the
* sql-error-codes.xml file. This method is used when this registry is used in an application context.
* <p>Note that any existing translators will remain unless there is a match in the database name at which
* point the new translator will replace the existing one.
*
* @param sqlExceptionTranslators
* Setter for a Map of {@link SQLExceptionTranslator} references where the key must
* be the database name as defined in the <code>sql-error-codes.xml</code> file.
* <p>Note that any existing translators will remain unless there is a match in the
* database name, at which point the new translator will replace the existing one.
*/
public void setSqlExceptionTranslators(Map<String, SQLExceptionTranslator> sqlExceptionTranslators) {
this.sqlExceptionTranslators.putAll(sqlExceptionTranslators);
public void setTranslators(Map<String, SQLExceptionTranslator> translators) {
this.translators.putAll(translators);
}
public void afterPropertiesSet() throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("Registering custom SQL exception translators for database(s): " +
sqlExceptionTranslators.keySet());
}
for (String dbName : sqlExceptionTranslators.keySet()) {
CustomSQLExceptionTranslatorRegistry.getInstance()
.registerSqlExceptionTranslator(dbName, sqlExceptionTranslators.get(dbName));
public void afterPropertiesSet() {
for (String dbName : this.translators.keySet()) {
CustomSQLExceptionTranslatorRegistry.getInstance().registerTranslator(dbName, this.translators.get(dbName));
}
}
}

View File

@@ -16,45 +16,25 @@
package org.springframework.jdbc.support;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.PatternMatchUtils;
/**
* Registry for custom {@link org.springframework.jdbc.support.SQLExceptionTranslator} instances associated with
* specific databases allowing for overriding translation based on values contained in the configuration file
* named "sql-error-codes.xml".
*
* @author Thomas Risberg
* @since 3.1
* @since 3.1.1
* @see SQLErrorCodesFactory
*/
public class CustomSQLExceptionTranslatorRegistry {
private static final Log logger = LogFactory.getLog(CustomSQLExceptionTranslatorRegistry.class);
/**
* Map registry to hold custom translators specific databases.
* Key is the database product name as defined in the
* {@link org.springframework.jdbc.support.SQLErrorCodesFactory}.
*/
private final Map<String, SQLExceptionTranslator> sqlExceptionTranslatorRegistry =
new HashMap<String, SQLExceptionTranslator>();
/**
* Keep track of a single instance so we can return it to classes that request it.
*/
@@ -70,7 +50,15 @@ public class CustomSQLExceptionTranslatorRegistry {
/**
* Create a new instance of the {@link org.springframework.jdbc.support.CustomSQLExceptionTranslatorRegistry} class.
* Map registry to hold custom translators specific databases.
* Key is the database product name as defined in the
* {@link org.springframework.jdbc.support.SQLErrorCodesFactory}.
*/
private final Map<String, SQLExceptionTranslator> translatorMap = new HashMap<String, SQLExceptionTranslator>();
/**
* Create a new instance of the {@link CustomSQLExceptionTranslatorRegistry} class.
* <p>Not public to enforce Singleton design pattern.
*/
private CustomSQLExceptionTranslatorRegistry() {
@@ -78,25 +66,28 @@ public class CustomSQLExceptionTranslatorRegistry {
/**
* Register a new custom translator for the specified database name.
*
* @param dbName the database name
* @param sqlExceptionTranslator the custom translator
* @param translator the custom translator
*/
public void registerSqlExceptionTranslator(String dbName, SQLExceptionTranslator sqlExceptionTranslator) {
SQLExceptionTranslator replaced = sqlExceptionTranslatorRegistry.put(dbName, sqlExceptionTranslator);
public void registerTranslator(String dbName, SQLExceptionTranslator translator) {
SQLExceptionTranslator replaced = translatorMap.put(dbName, translator);
if (replaced != null) {
logger.warn("Replacing custom translator '" + replaced +
"' for database " + dbName +
" with '" + sqlExceptionTranslator + "'");
logger.warn("Replacing custom translator [" + replaced + "] for database '" + dbName +
"' with [" + translator + "]");
}
else {
logger.info("Adding custom translator '" + sqlExceptionTranslator.getClass().getSimpleName() +
"' for database " + dbName);
logger.info("Adding custom translator of type [" + translator.getClass().getName() +
"] for database '" + dbName + "'");
}
}
public SQLExceptionTranslator findSqlExceptionTranslatorForDatabase(String dbName) {
return sqlExceptionTranslatorRegistry.get(dbName);
/**
* Find a custom translator for the specified database.
* @param dbName the database name
* @return the custom translator, or <code>null</code> if none found
*/
public SQLExceptionTranslator findTranslatorForDatabase(String dbName) {
return this.translatorMap.get(dbName);
}
}

View File

@@ -17,7 +17,6 @@
package org.springframework.jdbc.support;
import org.springframework.util.StringUtils;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
/**
* JavaBean for holding JDBC error codes for a particular database.
@@ -38,8 +37,6 @@ public class SQLErrorCodes {
private boolean useSqlStateForTranslation = false;
private SQLExceptionTranslator customSqlExceptionTranslator = null;
private String[] badSqlGrammarCodes = new String[0];
private String[] invalidResultSetAccessCodes = new String[0];
@@ -62,6 +59,8 @@ public class SQLErrorCodes {
private CustomSQLErrorCodesTranslation[] customTranslations;
private SQLExceptionTranslator customSqlExceptionTranslator;
/**
* Set this property if the database name contains spaces,
@@ -100,31 +99,6 @@ public class SQLErrorCodes {
return this.useSqlStateForTranslation;
}
public SQLExceptionTranslator getCustomSqlExceptionTranslator() {
return customSqlExceptionTranslator;
}
public void setCustomSqlExceptionTranslator(SQLExceptionTranslator customSqlExceptionTranslator) {
this.customSqlExceptionTranslator = customSqlExceptionTranslator;
}
public void setCustomSqlExceptionTranslatorClass(Class customSqlExceptionTranslatorClass) {
if (customSqlExceptionTranslatorClass != null) {
try {
this.customSqlExceptionTranslator =
(SQLExceptionTranslator) customSqlExceptionTranslatorClass.newInstance();
}
catch (InstantiationException e) {
throw new InvalidDataAccessResourceUsageException(
"Unable to instantiate " + customSqlExceptionTranslatorClass.getName(), e);
}
catch (IllegalAccessException e) {
throw new InvalidDataAccessResourceUsageException(
"Unable to instantiate " + customSqlExceptionTranslatorClass.getName(), e);
}
}
}
public void setBadSqlGrammarCodes(String[] badSqlGrammarCodes) {
this.badSqlGrammarCodes = StringUtils.sortStringArray(badSqlGrammarCodes);
}
@@ -213,4 +187,26 @@ public class SQLErrorCodes {
return this.customTranslations;
}
public void setCustomSqlExceptionTranslatorClass(Class<? extends SQLExceptionTranslator> customTranslatorClass) {
if (customTranslatorClass != null) {
try {
this.customSqlExceptionTranslator = customTranslatorClass.newInstance();
}
catch (Exception ex) {
throw new IllegalStateException("Unable to instantiate custom translator", ex);
}
}
else {
this.customSqlExceptionTranslator = null;
}
}
public void setCustomSqlExceptionTranslator(SQLExceptionTranslator customSqlExceptionTranslator) {
this.customSqlExceptionTranslator = customSqlExceptionTranslator;
}
public SQLExceptionTranslator getCustomSqlExceptionTranslator() {
return this.customSqlExceptionTranslator;
}
}

View File

@@ -17,7 +17,6 @@
package org.springframework.jdbc.support;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import javax.sql.DataSource;
@@ -171,7 +170,7 @@ public class SQLErrorCodesFactory {
}
}
if (sec != null) {
checkSqlExceptionTranslatorRegistry(dbName, sec);
checkCustomTranslatorRegistry(dbName, sec);
if (logger.isDebugEnabled()) {
logger.debug("SQL error codes for '" + dbName + "' found");
}
@@ -248,10 +247,12 @@ public class SQLErrorCodesFactory {
}
}
private void checkSqlExceptionTranslatorRegistry(String dbName, SQLErrorCodes dbCodes) {
// Check the custom sql exception translator registry for any entries
/**
* Check the {@link CustomSQLExceptionTranslatorRegistry} for any entries.
*/
private void checkCustomTranslatorRegistry(String dbName, SQLErrorCodes dbCodes) {
SQLExceptionTranslator customTranslator =
CustomSQLExceptionTranslatorRegistry.getInstance().findSqlExceptionTranslatorForDatabase(dbName);
CustomSQLExceptionTranslatorRegistry.getInstance().findTranslatorForDatabase(dbName);
if (customTranslator != null) {
if (dbCodes.getCustomSqlExceptionTranslator() != null) {
logger.warn("Overriding already defined custom translator '" +
@@ -265,7 +266,6 @@ public class SQLErrorCodesFactory {
}
dbCodes.setCustomSqlExceptionTranslator(customTranslator);
}
}
}