001: // $Id: SQLExceptionConverterFactory.java 4782 2004-11-21 00:11:27Z pgmjsd $
002: package org.hibernate.exception;
003:
004: import org.apache.commons.logging.Log;
005: import org.apache.commons.logging.LogFactory;
006: import org.hibernate.HibernateException;
007: import org.hibernate.JDBCException;
008: import org.hibernate.cfg.Environment;
009: import org.hibernate.dialect.Dialect;
010: import org.hibernate.util.ReflectHelper;
011: import org.hibernate.util.StringHelper;
012:
013: import java.lang.reflect.Constructor;
014: import java.sql.SQLException;
015: import java.util.Properties;
016:
017: /**
018: * A factory for building SQLExceptionConverter instances.
019: *
020: * @author Steve Ebersole
021: */
022: public class SQLExceptionConverterFactory {
023:
024: private static final Log log = LogFactory
025: .getLog(SQLExceptionConverterFactory.class);
026:
027: private SQLExceptionConverterFactory() {
028: // Private constructor - stops checkstyle from complaining.
029: }
030:
031: /**
032: * Build a SQLExceptionConverter instance.
033: * <p/>
034: * First, looks for a {@link Environment.SQL_EXCEPTION_CONVERTER} property to see
035: * if the configuration specified the class of a specific converter to use. If this
036: * property is set, attempt to construct an instance of that class. If not set, or
037: * if construction fails, the converter specific to the dialect will be used.
038: *
039: * @param dialect The defined dialect.
040: * @param properties The configuration properties.
041: * @return An appropriate SQLExceptionConverter instance.
042: * @throws HibernateException There was an error building the SQLExceptionConverter.
043: */
044: public static SQLExceptionConverter buildSQLExceptionConverter(
045: Dialect dialect, Properties properties)
046: throws HibernateException {
047: SQLExceptionConverter converter = null;
048:
049: String converterClassName = (String) properties
050: .get(Environment.SQL_EXCEPTION_CONVERTER);
051: if (StringHelper.isNotEmpty(converterClassName)) {
052: converter = constructConverter(converterClassName, dialect
053: .getViolatedConstraintNameExtracter());
054: }
055:
056: if (converter == null) {
057: log.trace("Using dialect defined converter");
058: converter = dialect.buildSQLExceptionConverter();
059: }
060:
061: if (converter instanceof Configurable) {
062: try {
063: ((Configurable) converter).configure(properties);
064: } catch (HibernateException e) {
065: log
066: .warn(
067: "Unable to configure SQLExceptionConverter",
068: e);
069: throw e;
070: }
071: }
072:
073: return converter;
074: }
075:
076: /**
077: * Builds a minimal converter. The instance returned here just always converts to
078: * {@link GenericJDBCException}.
079: *
080: * @return The minimal converter.
081: */
082: public static SQLExceptionConverter buildMinimalSQLExceptionConverter() {
083: return new SQLExceptionConverter() {
084: public JDBCException convert(SQLException sqlException,
085: String message, String sql) {
086: return new GenericJDBCException(message, sqlException,
087: sql);
088: }
089: };
090: }
091:
092: private static SQLExceptionConverter constructConverter(
093: String converterClassName,
094: ViolatedConstraintNameExtracter violatedConstraintNameExtracter) {
095: try {
096: log
097: .trace("Attempting to construct instance of specified SQLExceptionConverter ["
098: + converterClassName + "]");
099: Class converterClass = ReflectHelper
100: .classForName(converterClassName);
101:
102: // First, try to find a matching constructor accepting a ViolatedConstraintNameExtracter param...
103: Constructor[] ctors = converterClass
104: .getDeclaredConstructors();
105: for (int i = 0; i < ctors.length; i++) {
106: if (ctors[i].getParameterTypes() != null
107: && ctors[i].getParameterTypes().length == 1) {
108: if (ViolatedConstraintNameExtracter.class
109: .isAssignableFrom(ctors[i]
110: .getParameterTypes()[0])) {
111: try {
112: return (SQLExceptionConverter) ctors[i]
113: .newInstance(new Object[] { violatedConstraintNameExtracter });
114: } catch (Throwable t) {
115: // eat it and try next
116: }
117: }
118: }
119: }
120:
121: // Otherwise, try to use the no-arg constructor
122: return (SQLExceptionConverter) converterClass.newInstance();
123:
124: } catch (Throwable t) {
125: log
126: .warn(
127: "Unable to construct instance of specified SQLExceptionConverter",
128: t);
129: }
130:
131: return null;
132: }
133: }
|