Author: ppoddar
Date: Mon Dec 10 11:15:35 2007
New Revision: 603001

URL: http://svn.apache.org/viewvc?rev=603001&view=rev
Log:
OPENJPA-462: Narrow StoreException by SQLException.getSQLState()

Modified:
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
 Mon Dec 10 11:15:35 2007
@@ -98,7 +98,6 @@
 import org.apache.openjpa.util.InternalException;
 import org.apache.openjpa.util.InvalidStateException;
 import org.apache.openjpa.util.OpenJPAException;
-import org.apache.openjpa.util.ReferentialIntegrityException;
 import org.apache.openjpa.util.Serialization;
 import org.apache.openjpa.util.StoreException;
 import org.apache.openjpa.util.UnsupportedException;
@@ -150,6 +149,16 @@
     private static final String ZERO_TIMESTAMP_STR =
         "'" + new Timestamp(0) + "'";
 
+    public static final List EMPTY_STRING_LIST = Arrays.asList(new String[]{});
+    public static final List[] SQL_STATE_CODES = 
+       {EMPTY_STRING_LIST,                     // 0: Default
+        Arrays.asList(new String[]{"41000"}),  // 1: LOCK
+        EMPTY_STRING_LIST,                     // 2: OBJECT_NOT_FOUND
+        EMPTY_STRING_LIST,                     // 3: OPTIMISTIC
+        Arrays.asList(new String[]{"23000"}),  // 4: REFERENTIAL_INTEGRITY
+        EMPTY_STRING_LIST                      // 5: OBJECT_EXISTS
+       }; 
+                                              
     private static final Localizer _loc = Localizer.forPackage
         (DBDictionary.class);
 
@@ -4006,11 +4015,30 @@
      */
     public OpenJPAException newStoreException(String msg, SQLException[] 
causes,
         Object failed) {
-        if (causes.length > 0 && "23000".equals(causes[0].getSQLState()))
-            return new ReferentialIntegrityException(msg).
-                setFailedObject(failed).setNestedThrowables(causes);
+       if (causes != null && causes.length > 0) {
+               OpenJPAException ret = SQLExceptions.narrow(msg, causes[0], 
this);
+               ret.setFailedObject(failed).setNestedThrowables(causes);
+               return ret;
+       }
         return new StoreException(msg).setFailedObject(failed).
             setNestedThrowables(causes);
+    }
+    
+    /**
+     * Gets the list of String, each represents an error that can help 
+     * to narrow down a SQL exception to specific type of StoreException.<br>
+     * For example, error code <code>"23000"</code> represents referential
+     * integrity violation and hence can be narrowed down to 
+     * [EMAIL PROTECTED] ReferentialIntegrityException} rather than more 
general
+     * [EMAIL PROTECTED] StoreException}.<br>
+     * JDBC Drivers are not uniform in return values of SQLState for the same
+     * error and hence each database specific Dictionary can specialize.<br>
+     * Default behavior is to return an empty list. 
+     */
+    public List/*<String>*/ getSQLStates(int exceptionType) {
+       if (exceptionType>=0 && exceptionType<SQL_STATE_CODES.length)
+               return SQL_STATE_CODES[exceptionType];
+       return EMPTY_STRING_LIST;
     }
 
     /**

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
 Mon Dec 10 11:15:35 2007
@@ -23,7 +23,12 @@
 import java.util.List;
 
 import org.apache.openjpa.lib.util.Localizer.Message;
+import org.apache.openjpa.util.LockException;
+import org.apache.openjpa.util.ObjectExistsException;
+import org.apache.openjpa.util.ObjectNotFoundException;
 import org.apache.openjpa.util.OpenJPAException;
+import org.apache.openjpa.util.OptimisticException;
+import org.apache.openjpa.util.ReferentialIntegrityException;
 import org.apache.openjpa.util.StoreException;
 
 /**
@@ -96,7 +101,7 @@
                 setNestedThrowables(ses);
         return dict.newStoreException(msg, ses, failed);
     }
-
+    
     /**
      * Returns an array of [EMAIL PROTECTED] SQLException} instances for the
      * specified exception.
@@ -111,5 +116,33 @@
             se = se.getNextException();
         }
         return (SQLException[]) errs.toArray(new SQLException[errs.size()]);
+    }
+    
+    /**
+     * Narrows the given SQLException to a specific type of 
+     * [EMAIL PROTECTED] StoreException#getSubtype() StoreException} by 
analyzing the
+     * SQLState code supplied by SQLException. Each database-specific 
+     * [EMAIL PROTECTED] DBDictionary dictionary} can supply a set of error 
codes that will
+     * map to a specific specific type of StoreException via 
+     * [EMAIL PROTECTED] DBDictionary#getSQLStates(int) getSQLStates()} method.
+     * The default behavior is to return generic [EMAIL PROTECTED] 
StoreException 
+     * StoreException}.
+     */
+    public static OpenJPAException narrow(String msg, SQLException se, 
+               DBDictionary dict) {
+        String e = se.getSQLState();
+        if (dict.getSQLStates(StoreException.LOCK).contains(e)) 
+            return new LockException(msg);
+        else if (dict.getSQLStates(StoreException.OBJECT_EXISTS).contains(e))
+            return new ObjectExistsException(msg);
+        else if 
(dict.getSQLStates(StoreException.OBJECT_NOT_FOUND).contains(e))
+            return new ObjectNotFoundException(msg);
+        else if (dict.getSQLStates(StoreException.OPTIMISTIC).contains(e))
+            return new OptimisticException(msg);
+        else if (dict.getSQLStates(StoreException.REFERENTIAL_INTEGRITY)
+                       .contains(e)) 
+            return new ReferentialIntegrityException(msg);
+        else
+            return new StoreException(msg);
     }
 }

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
 Mon Dec 10 11:15:35 2007
@@ -28,6 +28,10 @@
 public class ObjectExistsException
     extends StoreException {
 
+    public ObjectExistsException(String msg) {
+               super(msg);
+    }
+       
     public ObjectExistsException(Message msg) {
         super(msg);
     }

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
 Mon Dec 10 11:15:35 2007
@@ -146,6 +146,7 @@
                         getFailedObject(ke), ke.isFatal());
                 break;
             case StoreException.OPTIMISTIC:
+            case StoreException.LOCK:
                 e = new org.apache.openjpa.persistence.OptimisticLockException
                     (ke.getMessage(), getNestedThrowables(ke),
                         getFailedObject(ke), ke.isFatal());


Reply via email to