Author: ppoddar
Date: Fri Mar 12 15:08:16 2010
New Revision: 922288

URL: http://svn.apache.org/viewvc?rev=922288&view=rev
Log:
OPENJPA-1565: Raise correct time out exception

Added:
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java
   (with props)
Modified:
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
    
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/InformixDictionary.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
    
openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/StoreException.java
    
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java
 Fri Mar 12 15:08:16 2010
@@ -35,6 +35,7 @@ import org.apache.openjpa.kernel.OpenJPA
 import org.apache.openjpa.kernel.StoreContext;
 import org.apache.openjpa.kernel.VersionLockManager;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.Exceptions;
 import org.apache.openjpa.util.LockException;
 
 /**
@@ -117,8 +118,7 @@ public class PessimisticLockManager
         JDBCFetchConfiguration fetch = _store.getFetchConfiguration();
         if (dict.simulateLocking)
             return;
-        dict.assertSupport(dict.supportsSelectForUpdate,
-            "SupportsSelectForUpdate");
+        dict.assertSupport(dict.supportsSelectForUpdate, 
"SupportsSelectForUpdate");
 
         Object id = sm.getObjectId();
         ClassMapping mapping = (ClassMapping) sm.getMetaData();
@@ -137,7 +137,7 @@ public class PessimisticLockManager
                 checkLock(rs, sm, timeout);
             }
         } catch (SQLException se) {
-            throw SQLExceptions.getStore(se, dict, level);
+            throw SQLExceptions.getStore(se, 
Exceptions.toString(sm.getPersistenceCapable()), dict, level);
         } finally {
             if (stmnt != null)
                 try { stmnt.close(); } catch (SQLException se) {}

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
 Fri Mar 12 15:08:16 2010
@@ -923,22 +923,18 @@ public class DB2Dictionary
     }
 
     @Override
-    protected Boolean matchErrorState(int subtype, Set<String> errorStates,
-        SQLException ex) {
-        Boolean recoverable = null;
+    protected boolean isFatalException(int subtype, SQLException ex) {
         String errorState = ex.getSQLState();
-        if (errorStates.contains(errorState)) {
-            recoverable = Boolean.FALSE;
-            if (subtype == StoreException.LOCK && errorState.equals("57033")
-                && ex.getMessage().indexOf("80") != -1) {
-                recoverable = Boolean.TRUE;
-            } else if ((subtype == StoreException.QUERY &&
-                errorState.equals("57014")) &&
-                (ex.getErrorCode() == -952 || ex.getErrorCode() == -905)) {
-                recoverable = Boolean.TRUE;
-            }
+        int errorCode = ex.getErrorCode();
+        if (subtype == StoreException.LOCK && "57033".equals(errorState)
+            && ex.getMessage().indexOf("80") != -1) {
+            return false;
+        } 
+        if ((subtype == StoreException.QUERY && "57014".equals(errorState) &&
+            (errorCode == -952 || errorCode == -905))) {
+            return false;
         }
-        return recoverable;
+        return super.isFatalException(subtype, ex);
     }
     
     @Override

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=922288&r1=922287&r2=922288&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
 Fri Mar 12 15:08:16 2010
@@ -110,6 +110,7 @@ import org.apache.openjpa.lib.util.Local
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.meta.ValueStrategies;
+import org.apache.openjpa.util.ExceptionInfo;
 import org.apache.openjpa.util.GeneralException;
 import org.apache.openjpa.util.InternalException;
 import org.apache.openjpa.util.InvalidStateException;
@@ -4777,10 +4778,9 @@ public class DBDictionary
      * be determined by the implementation. This may take into account
      * DB-specific exception information in <code>causes</code>.
      */
-    public OpenJPAException newStoreException(String msg, SQLException[] 
causes,
-        Object failed) {
+    public OpenJPAException newStoreException(String msg, SQLException[] 
causes, Object failed) {
         if (causes != null && causes.length > 0) {
-            OpenJPAException ret = narrow(msg, causes[0]);
+            OpenJPAException ret = narrow(msg, causes[0], failed);
             ret.setFailedObject(failed).setNestedThrowables(causes);
             return ret;
         }
@@ -4789,36 +4789,29 @@ public class DBDictionary
     }
     
     /**
-     * Gets the subtype of StoreException by matching the given SQLException's
+     * Gets the category of StoreException by matching the given SQLException's
      * error state code to the list of error codes supplied by the dictionary.
-     * Returns -1 if no matching code can be found.
+     * 
+     * @return a StoreException of {...@link ExceptionInfo#GENERAL general} 
category
+     * if the given SQL Exception can not be further categorized.
+     * 
+     * @see #matchErrorState(Map, SQLException)
      */
-    OpenJPAException narrow(String msg, SQLException ex) {
-        Boolean recoverable = null;
-        int errorType = StoreException.GENERAL;
-        for (Integer type : sqlStateCodes.keySet()) {
-            Set<String> errorStates = sqlStateCodes.get(type);
-            if (errorStates != null) {
-                recoverable = matchErrorState(type, errorStates, ex);
-                if (recoverable != null) {
-                    errorType = type;
-                    break;
-                }
-            }
-        }
+    OpenJPAException narrow(String msg, SQLException ex, Object failed) {
+        int errorType = matchErrorState(sqlStateCodes, ex);
         StoreException storeEx;
         switch (errorType) {
         case StoreException.LOCK:
-            storeEx = new LockException(msg);
+            storeEx = new LockException(failed);
             break;
         case StoreException.OBJECT_EXISTS:
             storeEx = new ObjectExistsException(msg);
             break;
         case StoreException.OBJECT_NOT_FOUND:
-            storeEx = new ObjectNotFoundException(msg);
+            storeEx = new ObjectNotFoundException(failed);
             break;
         case StoreException.OPTIMISTIC:
-            storeEx = new OptimisticException(msg);
+            storeEx = new OptimisticException(failed);
             break;
         case StoreException.REFERENTIAL_INTEGRITY:
             storeEx = new ReferentialIntegrityException(msg);
@@ -4829,24 +4822,48 @@ public class DBDictionary
         default:
             storeEx = new StoreException(msg);
         }
-        if (recoverable != null) {
-            storeEx.setFatal(!recoverable);
-        }
+        storeEx.setFatal(isFatalException(errorType, ex));
         return storeEx;
     }
 
     /**
-     * Determine if the SQLException argument matches any element in the
-     * errorStates. Dictionary subclass can override this method and extract
+     * Determine the more appropriate type of store exception by matching the 
SQL Error State of the
+     * the given SQLException to the given Error States categorized by error 
types.
+     * Dictionary subclass can override this method and extract
      * SQLException data to figure out if the exception is recoverable.
      * 
-     * @return null if no match is found or a Boolean value indicates the
-     * exception is recoverable.
+     * @param errorStates classification of SQL error states by their specific 
nature. The keys of the
+     * map represent one of the constants defined in {...@link 
StoreException}. The value corresponding to
+     * a key represent the set of SQL Error States representing specific 
category of database error. 
+     * This supplied map is sourced from <code>sql-error-state-codes.xml</xml> 
and filtered the
+     * error states for the current database.
+     * 
+     * @param ex original SQL Exception as raised by the database driver.
+     * 
+     * @return A constant indicating the category of error as defined in 
{...@link StoreException}.
      */
-    protected Boolean matchErrorState(int subtype, Set<String> errorStates,
-        SQLException ex) {
+    protected int matchErrorState(Map<Integer,Set<String>> errorStates, 
SQLException ex) {
         String errorState = ex.getSQLState();
-        return errorStates.contains(errorState) ? Boolean.FALSE : null;
+        for (Map.Entry<Integer,Set<String>> states : errorStates.entrySet()) {
+            if (states.getValue().contains(errorState))
+                return states.getKey();
+        }
+        return StoreException.GENERAL;
+    }
+    
+    /**
+     * Determine if the given SQL Exception is fatal or recoverable (such as a 
timeout).
+     * This implementation always returns true (i.e. all exceptions are fatal).
+     * The current dictionary implementation can overwrite this method to mark 
certain
+     * exception conditions as recoverable error.
+
+     * @param subtype A constant indicating the category of error as defined 
in {...@link StoreException}. 
+     * @param ex original SQL Exception as raised by the database driver.
+     * 
+     * @return false if the error is fatal. 
+     */
+    protected boolean isFatalException(int subtype, SQLException ex) {
+        return true;
     }
     
     /**

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
 Fri Mar 12 15:08:16 2010
@@ -377,23 +377,17 @@ public class InformixDictionary
     }
         
     @Override
-    protected Boolean matchErrorState(int subtype, Set<String> errorStates,
-        SQLException ex) {
-        Boolean recoverable = null;
-        String errorState = ex.getSQLState();
-        if (errorStates.contains(errorState)) {
-            // SQL State of IX000 is a general purpose Informix error code
-            // category, so only return Boolean.TRUE if we match SQL Codes
-            // recoverable = Boolean.FALSE;
-            if (subtype == StoreException.LOCK &&
-                ex.getErrorCode() == -154) {
-                recoverable = Boolean.TRUE;
-            } else if (subtype == StoreException.QUERY &&
-                ex.getErrorCode() == -213) {
-                recoverable = Boolean.TRUE;
-            }
+    protected boolean isFatalException(int subtype, SQLException ex) {
+        
+        // SQL State of IX000 is a general purpose Informix error code
+        // category, so only return Boolean.TRUE if we match SQL Codes
+        // recoverable = Boolean.FALSE;
+        if ((subtype == StoreException.LOCK && ex.getErrorCode() == -154) 
+          ||(subtype == StoreException.QUERY && ex.getErrorCode() == -213)) {
+            return false;
         }
-        return recoverable;
+        
+        return super.isFatalException(subtype, ex);
     }
 }
 

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
 Fri Mar 12 15:08:16 2010
@@ -1259,25 +1259,21 @@ public class OracleDictionary
     }
     
     @Override
-    protected Boolean matchErrorState(int subtype, Set<String> errorStates,
-        SQLException ex) {
-        Boolean recoverable = null;
+    protected boolean isFatalException(int subtype, SQLException ex) {
         String errorState = ex.getSQLState();
         int errorCode = ex.getErrorCode();
-        if (errorStates.contains(errorState)) {
-            recoverable = Boolean.FALSE;
-            if ((subtype == StoreException.LOCK)
-                && ((errorState.equals("61000") && (errorCode == 54 ||
-                     errorCode == 60 || errorCode == 4020 ||
-                     errorCode == 4021 || errorCode == 4022))
-                    || (errorState.equals("42000") && errorCode == 2049))) {
-                recoverable = Boolean.TRUE;
-            } else if (subtype == StoreException.QUERY &&
-                errorState.equals("72000") && errorCode == 1013) {
-                recoverable = Boolean.TRUE;
-            }
+        if ((subtype == StoreException.LOCK)
+            && (("61000".equals(errorState) && (errorCode == 54 ||
+                 errorCode == 60 || errorCode == 4020 ||
+                 errorCode == 4021 || errorCode == 4022))
+                || ("42000".equals(errorState) && errorCode == 2049))) {
+            return false;
+        } 
+        if (subtype == StoreException.QUERY &&
+            "72000".equals(errorState) && errorCode == 1013) {
+            return false;
         }
-        return recoverable;
+        return super.isFatalException(subtype, ex);
     }
     
     @Override

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
 Fri Mar 12 15:08:16 2010
@@ -29,7 +29,7 @@
 <sql-state-codes>
 
        <dictionary class="org.apache.openjpa.jdbc.sql.DB2Dictionary">
-               <lock>40001,57033,57011</lock>
+               <lock>40001,57033,57011,57014</lock>
                
<referential-integrity>23502,42912,23001,23504,23511,23512,23513,23515,23520</referential-integrity>
                <object-exists>23505</object-exists>
                <object-not-found></object-not-found>
@@ -155,12 +155,12 @@
        </dictionary>
        
        <dictionary class="org.apache.openjpa.jdbc.sql.MySQLDictionary">
-               <lock>1205,1213</lock>
+               <lock>41000</lock>
                
<referential-integrity>630,839,840,893,1062,1169,1215,1216,1217,1451,1452,1557</referential-integrity>
                <object-exists>23000</object-exists>
                <object-not-found></object-not-found>
-               <optimistic>41000</optimistic>
-               <query></query>
+               <optimistic></optimistic>
+               <query>70100</query>
        </dictionary>
        
        <dictionary class="org.apache.openjpa.jdbc.sql.OracleDictionary">

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
 Fri Mar 12 15:08:16 2010
@@ -245,11 +245,30 @@ public class Filters {
             return true;
         return false;
     }
+    
+    /**
+     * Convert the given value to match the given (presumably a setter) method 
argument type.
+     *  
+     * @param o given value
+     * @param method a presumably setter method 
+     * 
+     * @return the same value if the method does not have one and only one 
input argument.
+     */
+    public static Object convertToMatchMethodArgument(Object o, Method method) 
{
+        if (method == null || method.getParameterTypes().length != 1) {
+            return o;
+        }
+        return convert(o, method.getParameterTypes()[0], true);
+    }
 
+    public static Object convert(Object o, Class<?> type) {
+        return convert(o, type, false);
+    }
+    
     /**
      * Convert the given value to the given type.
      */
-    public static Object convert(Object o, Class<?> type) {
+    public static Object convert(Object o, Class<?> type, boolean 
strictNumericConversion) {
         if (o == null)
             return null;
         if (o.getClass() == type)
@@ -315,13 +334,13 @@ public class Filters {
             throw new ClassCastException(_loc.get("cant-convert", o,
                 o.getClass(), type).getMessage());
 
-        if (type == Integer.class) {
+        if (type == Integer.class && allowNumericConversion(o.getClass(), 
type, strictNumericConversion)) {
             return ((Number) o).intValue();
-        } else if (type == Float.class) {
+        } else if (type == Float.class && allowNumericConversion(o.getClass(), 
type, strictNumericConversion)) {
             return new Float(((Number) o).floatValue());
         } else if (type == Double.class) {
             return new Double(((Number) o).doubleValue());
-        } else if (type == Long.class) {
+        } else if (type == Long.class && allowNumericConversion(o.getClass(), 
type, strictNumericConversion)) {
             return ((Number) o).longValue();
         } else if (type == BigDecimal.class) {
             // the BigDecimal constructor doesn't handle the
@@ -339,14 +358,28 @@ public class Filters {
             return new BigDecimal(o.toString());
         } else if (type == BigInteger.class) {
             return new BigInteger(o.toString());
-        } else if (type == Short.class) {
+        } else if (type == Short.class && allowNumericConversion(o.getClass(), 
type, strictNumericConversion)) {
             return new Short(((Number) o).shortValue());
-        } else if (type == Byte.class) {
+        } else if (type == Byte.class && allowNumericConversion(o.getClass(), 
type, strictNumericConversion)) {
             return new Byte(((Number) o).byteValue());
-        } else {
+        } else if (!strictNumericConversion) {
             return ((Number) o).intValue();
+        } else {
+            throw new ClassCastException(_loc.get("cant-convert", o, 
o.getClass(), type).getMessage());
         }
     }
+    
+    private static boolean allowNumericConversion(Class<?> actual, Class<?> 
target, boolean strict) {
+        if (!strict || actual == target)
+            return true;
+        if (actual == Byte.class)    return false;
+        if (actual == Double.class)  return target == Float.class;
+        if (actual == Float.class)   return target == Double.class;
+        if (actual == Integer.class) return target == Long.class || target == 
Short.class;
+        if (actual == Long.class)    return target == Integer.class || target 
== Short.class;
+        if (actual == Short.class)   return target == Long.class || target == 
Integer.class;
+        return false;
+    }
 
     /**
      * Add the given values.

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java
 Fri Mar 12 15:08:16 2010
@@ -30,13 +30,13 @@ import org.apache.openjpa.lib.util.Local
  * @author Marc Prud'hommeaux
  * @since 0.3.1
  */
+...@suppresswarnings("serial")
 public class LockException
     extends StoreException {
 
-    private static final transient Localizer _loc = Localizer.forPackage
-        (LockException.class);
+    private static final transient Localizer _loc = 
Localizer.forPackage(LockException.class);
 
-    private int timeout = -1;
+    private int timeout   = -1;
     private int lockLevel = -1;
     
     public LockException(Object failed) {
@@ -49,8 +49,7 @@ public class LockException
     }
     
     public LockException(Object failed, int timeout, int lockLevel) {
-        super(_loc.get("lock-timeout", Exceptions.toString(failed),
-            String.valueOf(timeout)));
+        super(_loc.get("lock-timeout", Exceptions.toString(failed), 
String.valueOf(timeout)));
         setFailedObject(failed);
         setTimeout(timeout);
     }
@@ -86,8 +85,7 @@ public class LockException
         String str = super.toString();
         if (timeout < 0)
             return str;
-        return str + Exceptions.SEP + "Timeout: " + timeout + ", LockLevel"
-            + lockLevel;
+        return str + Exceptions.SEP + "Timeout: " + timeout + ", LockLevel" + 
lockLevel;
     }
 
     private void writeObject(ObjectOutputStream out)

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java
 Fri Mar 12 15:08:16 2010
@@ -35,6 +35,7 @@ import org.apache.openjpa.lib.util.Local
  * @author Abe White
  * @since 0.4.0
  */
+...@suppresswarnings("serial")
 public abstract class OpenJPAException
     extends RuntimeException
     implements Serializable, ExceptionInfo {

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/StoreException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/StoreException.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/StoreException.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/StoreException.java
 Fri Mar 12 15:08:16 2010
@@ -26,6 +26,7 @@ import org.apache.openjpa.lib.util.Local
  * @author Marc Prud'hommeaux
  * @since 0.2.5
  */
+...@suppresswarnings("serial")
 public class StoreException
     extends OpenJPAException {
 

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java?rev=922288&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java
 Fri Mar 12 15:08:16 2010
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.apache.openjpa.persistence.query;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import javax.persistence.EntityManager;
+import javax.persistence.LockModeType;
+import javax.persistence.LockTimeoutException;
+import javax.persistence.Query;
+import javax.persistence.QueryTimeoutException;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.openjpa.persistence.exception.PObject;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Tests that correct timeout exceptions are being thrown depending on whether 
it is a query or a lock operation.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class TestTimeoutException extends SingleEMFTestCase {
+    private final Class<?> entityClass = PObject.class;
+    private final ExecutorService scheduler = Executors.newCachedThreadPool();
+    public void setUp() {
+        super.setUp(entityClass);
+    }
+    
+    public void 
testQueryTimeOutExceptionWhileQueryingWithLocksOnAlreadyLockedEntities() {
+        EntityManager em1 = emf.createEntityManager();
+        EntityManager em2 = emf.createEntityManager();
+        assertNotSame(em1, em2);
+        Object oid = createEntity(em1);
+        
+        em1.getTransaction().begin();
+        Object entity = em1.find(entityClass, oid);
+        assertNotNull(entity);
+        em1.lock(entity, LockModeType.PESSIMISTIC_WRITE);
+        
+        em2.getTransaction().begin();
+        final Query query = em2.createQuery("select p from PObject p");
+        query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
+        long timeout = 1000;
+        query.setHint("javax.persistence.query.timeout", timeout);
+        assertError(new Callable<Throwable>() {
+            public Throwable call() throws Exception {
+                try {
+                    query.getResultList();
+                } catch (Throwable t) {
+                    return t;
+                }
+                return null;
+            }
+        }, QueryTimeoutException.class, timeout);
+        
+        assertTrue(em2.getTransaction().isActive());
+        em2.getTransaction().rollback();
+        em1.getTransaction().rollback();
+    }
+    
+    public void testLockTimeOutExceptionWhileLockingAlreadyLockedEntities() {
+        EntityManager em1 = emf.createEntityManager();
+        final EntityManager em2 = emf.createEntityManager();
+        assertNotSame(em1, em2);
+        final Object oid = createEntity(em1);
+        
+        em1.getTransaction().begin();
+        final Object entity1 = em1.find(entityClass, oid);
+        assertNotNull(entity1);
+        em1.lock(entity1, LockModeType.PESSIMISTIC_WRITE);
+        
+        em2.getTransaction().begin();
+        final Object entity2 = em2.find(entityClass, oid);
+        final long timeout = 1000;
+        assertError(new Callable<Throwable>() {
+            public Throwable call() throws Exception {
+                try {
+                    Map<String,Object> hint = new HashMap<String, Object>();
+                    hint.put("javax.persistence.lock.timeout", timeout);
+                    em2.lock(entity2, LockModeType.PESSIMISTIC_WRITE, hint);
+                } catch (Throwable t) {
+                    return t;
+                }
+                return null;
+            }
+        }, LockTimeoutException.class, timeout);
+        assertTrue(em2.getTransaction().isActive());
+        em2.getTransaction().rollback();
+        
+        em1.getTransaction().rollback();
+    }
+
+    
+    public Object createEntity(EntityManager em) {
+        long id = System.nanoTime();
+        em.getTransaction().begin();
+        PObject pc = new PObject();
+        pc.setId(id);
+        em.persist(pc);
+        em.getTransaction().commit();
+        return id;
+    }
+    
+    
+    /**
+     * Assert that an exception of proper type has been thrown by the given 
task within the given timeout.
+     * @param t
+     * @param expeceted
+     */
+    void assertError(Callable<Throwable> task, Class<? extends Throwable> 
expected, long timeout) {
+        try {
+            Future<Throwable> future = scheduler.submit(task);
+            Throwable error = future.get();
+            if (error == null) {
+                throw new AssertionFailedError("No exception was raised but 
expected " + expected.getName());
+            } else if (!expected.isAssignableFrom(error.getClass())) {
+                error.printStackTrace();
+                throw new AssertionFailedError(error.getClass().getName() + " 
was raised but expected " + 
+                        expected.getName());
+            }
+        } catch (Throwable t) {
+            t.printStackTrace();
+            throw new AssertionFailedError(t.getClass().getName() + " was 
raised but expected " + 
+                    expected.getName());
+        }
+    }   
+    
+}

Propchange: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
 Fri Mar 12 15:08:16 2010
@@ -30,6 +30,7 @@ import javax.persistence.QueryTimeoutExc
 
 import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.persistence.LockTimeoutException;
 import org.apache.openjpa.persistence.test.SQLListenerTestCase;
 
 /**
@@ -40,6 +41,7 @@ public class TestPessimisticLocks extend
     private DBDictionary dict = null;
 
     public void setUp() {
+        setUp(Employee.class, Department.class, "openjpa.LockManager", 
"mixed");
         setSupportedDatabases(
                 org.apache.openjpa.jdbc.sql.DerbyDictionary.class,
 //                org.apache.openjpa.jdbc.sql.OracleDictionary.class,
@@ -48,7 +50,6 @@ public class TestPessimisticLocks extend
             return;
         }
 
-        setUp(Employee.class, Department.class, "openjpa.LockManager", 
"mixed");
         String empTable = getMapping(Employee.class).getTable().getFullName();
         String deptTable = 
getMapping(Department.class).getTable().getFullName();
 
@@ -125,10 +126,11 @@ public class TestPessimisticLocks extend
             // find Employee(2) with a lock, should block and expected a 
PessimisticLockException
             em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
             fail("Unexcpected find succeeded. Should throw a 
PessimisticLockException.");
-        } catch (QueryTimeoutException e) {            
+        } catch (LockTimeoutException e) {            
             // TODO: DB2: This is the current unexpected exception due to 
OPENJPA-991.
             // Remove this when the problem is fixed
-//            System.out.println("Caught " + e.getClass().getName() + ":" + 
e.getMessage());
+            System.out.println("Caught " + e.getClass().getName() + ":" + 
e.getMessage() + " Failed " 
+                    + e.getFailedObject());
         } catch (PessimisticLockException e) {
             // TODO: This is the expected exception but will be fixed under 
OPENJPA-991
 //            System.out.println("Caught " + e.getClass().getName() + ":" + 
e.getMessage());
@@ -208,10 +210,11 @@ public class TestPessimisticLocks extend
             // find Employee(2) with a lock, should block and expected a 
PessimisticLockException
             em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
             fail("Unexcpected find succeeded. Should throw a 
PessimisticLockException.");
-        } catch (QueryTimeoutException e) {            
+        } catch (LockTimeoutException e) {            
             // TODO: DB2: This is the current unexpected exception due to 
OPENJPA-991.
             // Remove this when the problem is fixed
-//            System.out.println("Caught " + e.getClass().getName() + ":" + 
e.getMessage());
+            System.out.println("Caught " + e.getClass().getName() + ":" + 
e.getMessage() + " Failed " + 
+                    e.getFailedObject());
         } catch (PessimisticLockException e) {
             // TODO: This is the expected exception but will be fixed under 
OPENJPA-991
 //            System.out.println("Caught " + e.getClass().getName() + ":" + 
e.getMessage());

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java
 Fri Mar 12 15:08:16 2010
@@ -35,6 +35,7 @@ import org.apache.openjpa.util.StoreExce
  * @since 2.0.0
  * @nojavadoc
  */
+...@suppresswarnings("serial")
 public class LockTimeoutException
     extends javax.persistence.LockTimeoutException
     implements Serializable, ExceptionInfo {
@@ -43,12 +44,10 @@ public class LockTimeoutException
     private transient Object _failed = null;
     private transient Throwable[] _nested = null;
 
-    public LockTimeoutException(String msg, Throwable[] nested,
-        Object failed, boolean fatal) {
+    public LockTimeoutException(String msg, Throwable[] nested,  Object 
failed) {
         super(msg);
         _nested = nested;
         _failed = failed;
-        _fatal = fatal;
     }
 
     public int getType() {

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=922288&r1=922287&r2=922288&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
 Fri Mar 12 15:08:16 2010
@@ -151,63 +151,40 @@ public class PersistenceExceptions
      */
     private static Throwable translateStoreException(OpenJPAException ke) {
         Exception e;
+        int subtype = ke.getSubtype();
+        String msg  = ke.getMessage();
+        Throwable[] nested = getNestedThrowables(ke);
+        Object failed = getFailedObject(ke);
+        boolean fatal = ke.isFatal();
         Throwable cause = (ke.getNestedThrowables() != null
                         && ke.getNestedThrowables().length == 1)
                          ? ke.getNestedThrowables()[0] : null;
-        if (ke.getSubtype() == StoreException.OBJECT_NOT_FOUND
-         || cause instanceof ObjectNotFoundException) {
-                e = new org.apache.openjpa.persistence.EntityNotFoundException
-                    (ke.getMessage(), getNestedThrowables(ke),
-                        getFailedObject(ke), ke.isFatal());
-        } else if (ke.getSubtype() == StoreException.OPTIMISTIC
-                       || cause instanceof OptimisticException) {
-               e = new org.apache.openjpa.persistence.OptimisticLockException
-                    (ke.getMessage(), getNestedThrowables(ke),
-                        getFailedObject(ke), ke.isFatal());
-        } else if (ke.getSubtype() == StoreException.LOCK
-                || cause instanceof LockException) {
-            LockException lockEx = (LockException)
-                (ke instanceof LockException ? ke : cause);
-            if (lockEx != null && lockEx.getLockLevel() >=
-                MixedLockLevels.LOCK_PESSIMISTIC_READ) {
+        if (subtype == StoreException.OBJECT_NOT_FOUND || cause instanceof 
ObjectNotFoundException) {
+                e = new 
org.apache.openjpa.persistence.EntityNotFoundException(msg, nested, failed, 
fatal);
+        } else if (subtype == StoreException.OPTIMISTIC        || cause 
instanceof OptimisticException) {
+               e = new 
org.apache.openjpa.persistence.OptimisticLockException(msg, nested, failed, 
fatal);
+        } else if (subtype == StoreException.LOCK || cause instanceof 
LockException) {
+            LockException lockEx = (LockException) (ke instanceof 
LockException ? ke : cause);
+            if (lockEx != null && lockEx.getLockLevel() >= 
MixedLockLevels.LOCK_PESSIMISTIC_READ) {
                 if (!lockEx.isFatal()) {
-                    e = new org.apache.openjpa.persistence
-                        .LockTimeoutException(
-                        ke.getMessage(), getNestedThrowables(ke),
-                        getFailedObject(ke), ke.isFatal());
+                    e = new 
org.apache.openjpa.persistence.LockTimeoutException(msg, nested, failed);
                 } else {
-                    e = new org.apache.openjpa.persistence
-                        .PessimisticLockException(
-                        ke.getMessage(), getNestedThrowables(ke),
-                        getFailedObject(ke), ke.isFatal());
+                    e = new 
org.apache.openjpa.persistence.PessimisticLockException(msg, nested, failed);
                 }
             } else {
-                e = new org.apache.openjpa.persistence.OptimisticLockException(
-                    ke.getMessage(), getNestedThrowables(ke),
-                    getFailedObject(ke), ke.isFatal());
+                e = new 
org.apache.openjpa.persistence.OptimisticLockException(msg, nested, failed, 
fatal);
             }
-        } else if (ke.getSubtype() == StoreException.OBJECT_EXISTS
-                       || cause instanceof ObjectExistsException) {
-                e = new org.apache.openjpa.persistence.EntityExistsException
-                    (ke.getMessage(), getNestedThrowables(ke),
-                        getFailedObject(ke), ke.isFatal());
-        } else if (ke.getSubtype() == StoreException.QUERY
-                || cause instanceof QueryException) {
-            QueryException queryEx = (QueryException)
-                (ke instanceof QueryException ? ke : cause);
+        } else if (subtype == StoreException.OBJECT_EXISTS || cause instanceof 
ObjectExistsException) {
+                e = new 
org.apache.openjpa.persistence.EntityExistsException(msg, nested, failed, 
fatal);
+        } else if (subtype == StoreException.QUERY || cause instanceof 
QueryException) {
+            QueryException queryEx = (QueryException) (ke instanceof 
QueryException ? ke : cause);
             if (!queryEx.isFatal()) {
-                e = new org.apache.openjpa.persistence.QueryTimeoutException(
-                    ke.getMessage(), getNestedThrowables(ke),
-                    getFailedObject(ke), ke.isFatal());
+                e = new 
org.apache.openjpa.persistence.QueryTimeoutException(msg, nested, failed, 
false);
             } else {
-                e = new org.apache.openjpa.persistence.PersistenceException(
-                    ke.getMessage(), getNestedThrowables(ke),
-                    getFailedObject(ke), ke.isFatal());
+                e = new 
org.apache.openjpa.persistence.PersistenceException(msg, nested, failed, true);
             }
         } else {
-                e = new org.apache.openjpa.persistence.PersistenceException
-                    (ke.getMessage(), getNestedThrowables(ke),
-                        getFailedObject(ke), ke.isFatal());
+            e = new org.apache.openjpa.persistence.PersistenceException(msg, 
nested, failed, fatal);
         }
         e.setStackTrace(ke.getStackTrace());
         return e;

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java
 Fri Mar 12 15:08:16 2010
@@ -31,24 +31,24 @@ import org.apache.openjpa.util.StoreExce
 
 /**
  * Pessimistic concurrency violation.
+ * This exception is always fatal in contrast to {...@linkplain 
LockTimeoutException}.
  *
  * @since 2.0.0
  * @nojavadoc
  */
+...@suppresswarnings("serial")
 public class PessimisticLockException
     extends javax.persistence.PessimisticLockException
     implements Serializable, ExceptionInfo {
 
-    private transient boolean _fatal = false;
+    private transient boolean _fatal = true;
     private transient Object _failed = null;
     private transient Throwable[] _nested = null;
 
-    public PessimisticLockException(String msg, Throwable[] nested,
-        Object failed, boolean fatal) {
+    public PessimisticLockException(String msg, Throwable[] nested, Object 
failed) {
         super(msg);
         _nested = nested;
         _failed = failed;
-        _fatal = fatal;
     }
 
     public int getType() {

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
 Fri Mar 12 15:08:16 2010
@@ -293,7 +293,7 @@ public class QueryImpl<X> implements Ope
             }
             return result;
                } catch (LockTimeoutException e) {
-                   throw new QueryTimeoutException(e.getMessage(), new 
Throwable[]{e}, getQueryString(), e.isFatal());
+                   throw new QueryTimeoutException(e.getMessage(), new 
Throwable[]{e}, this);
                } finally {
                    unlock();
                }

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java?rev=922288&r1=922287&r2=922288&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java
 Fri Mar 12 15:08:16 2010
@@ -35,6 +35,7 @@ import org.apache.openjpa.util.StoreExce
  * @since 2.0.0
  * @nojavadoc
  */
+...@suppresswarnings("serial")
 public class QueryTimeoutException
     extends javax.persistence.QueryTimeoutException
     implements Serializable, ExceptionInfo {
@@ -43,8 +44,11 @@ public class QueryTimeoutException
     private transient Object _failed = null;
     private transient Throwable[] _nested = null;
 
-    public QueryTimeoutException(String msg, Throwable[] nested,
-        Object failed, boolean fatal) {
+    public QueryTimeoutException(String msg, Throwable[] nested, Object 
failed) {
+        this(msg, nested, failed, false);
+    }
+    
+    public QueryTimeoutException(String msg, Throwable[] nested, Object 
failed, boolean fatal) {
         super(msg);
         _nested = nested;
         _failed = failed;


Reply via email to