1 16 17 package org.springframework.jdbc.support; 18 19 import java.util.Collections ; 20 import java.util.HashMap ; 21 import java.util.Iterator ; 22 import java.util.Map ; 23 24 import javax.sql.DataSource ; 25 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 29 import org.springframework.beans.BeansException; 30 import org.springframework.beans.factory.support.DefaultListableBeanFactory; 31 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; 32 import org.springframework.core.io.ClassPathResource; 33 import org.springframework.core.io.Resource; 34 import org.springframework.util.Assert; 35 import org.springframework.util.PatternMatchUtils; 36 37 51 public class SQLErrorCodesFactory { 52 53 57 public static final String SQL_ERROR_CODE_OVERRIDE_PATH = "sql-error-codes.xml"; 58 59 62 public static final String SQL_ERROR_CODE_DEFAULT_PATH = "org/springframework/jdbc/support/sql-error-codes.xml"; 63 64 65 private static final Log logger = LogFactory.getLog(SQLErrorCodesFactory.class); 66 67 70 private static final SQLErrorCodesFactory instance = new SQLErrorCodesFactory(); 71 72 73 76 public static SQLErrorCodesFactory getInstance() { 77 return instance; 78 } 79 80 81 85 private final Map errorCodesMap; 86 87 91 private final Map dataSourceCache = new HashMap (16); 92 93 94 102 protected SQLErrorCodesFactory() { 103 Map errorCodes = null; 104 105 try { 106 DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); 107 XmlBeanDefinitionReader bdr = new XmlBeanDefinitionReader(lbf); 108 109 Resource resource = loadResource(SQL_ERROR_CODE_DEFAULT_PATH); 111 if (resource != null && resource.exists()) { 112 bdr.loadBeanDefinitions(resource); 113 } 114 else { 115 logger.warn("Default sql-error-codes.xml not found (should be included in spring.jar)"); 116 } 117 118 resource = loadResource(SQL_ERROR_CODE_OVERRIDE_PATH); 120 if (resource != null && resource.exists()) { 121 bdr.loadBeanDefinitions(resource); 122 logger.info("Found custom sql-error-codes.xml file at the root of the classpath"); 123 } 124 125 errorCodes = lbf.getBeansOfType(SQLErrorCodes.class, true, false); 127 if (logger.isInfoEnabled()) { 128 logger.info("SQLErrorCodes loaded: " + errorCodes.keySet()); 129 } 130 } 131 catch (BeansException ex) { 132 logger.warn("Error loading SQL error codes from config file", ex); 133 errorCodes = Collections.EMPTY_MAP; 134 } 135 136 this.errorCodesMap = errorCodes; 137 } 138 139 150 protected Resource loadResource(String path) { 151 return new ClassPathResource(path); 152 } 153 154 155 162 public SQLErrorCodes getErrorCodes(String dbName) { 163 Assert.notNull(dbName, "Database product name must not be null"); 164 165 SQLErrorCodes sec = (SQLErrorCodes) this.errorCodesMap.get(dbName); 166 if (sec == null) { 167 for (Iterator it = this.errorCodesMap.values().iterator(); it.hasNext();) { 168 SQLErrorCodes candidate = (SQLErrorCodes) it.next(); 169 if (PatternMatchUtils.simpleMatch(candidate.getDatabaseProductNames(), dbName)) { 170 sec = candidate; 171 break; 172 } 173 } 174 } 175 if (sec != null) { 176 if (logger.isDebugEnabled()) { 177 logger.debug("SQL error codes for '" + dbName + "' found"); 178 } 179 return sec; 180 } 181 182 if (logger.isDebugEnabled()) { 184 logger.debug("SQL error codes for '" + dbName + "' not found"); 185 } 186 return new SQLErrorCodes(); 187 } 188 189 197 public SQLErrorCodes getErrorCodes(DataSource dataSource) { 198 Assert.notNull(dataSource, "DataSource must not be null"); 199 if (logger.isDebugEnabled()) { 200 logger.debug("Looking up default SQLErrorCodes for DataSource [" + dataSource + "]"); 201 } 202 203 synchronized (this.dataSourceCache) { 204 SQLErrorCodes sec = (SQLErrorCodes) this.dataSourceCache.get(dataSource); 206 if (sec != null) { 207 if (logger.isDebugEnabled()) { 208 logger.debug("SQLErrorCodes found in cache for DataSource [" + dataSource + "]"); 209 } 210 return sec; 211 } 212 try { 214 String dbName = (String ) 215 JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName"); 216 if (dbName != null) { 217 if (logger.isDebugEnabled()) { 218 logger.debug("Database product name cached for DataSource [" + dataSource + 219 "]: name is '" + dbName + "'"); 220 } 221 sec = getErrorCodes(dbName); 222 this.dataSourceCache.put(dataSource, sec); 223 return sec; 224 } 225 } 226 catch (MetaDataAccessException ex) { 227 logger.warn("Error while extracting database product name - falling back to empty error codes", ex); 228 } 229 } 230 231 return new SQLErrorCodes(); 233 } 234 235 } 236 | Popular Tags |