Bug #456067: Added support for defining query timeout units

Signed-off-by: Will Dazey <dazeydev.3@gmail.com>
diff --git a/foundation/eclipselink.core.test/.gitignore b/foundation/eclipselink.core.test/.gitignore
index 8ba548b..b28749f 100644
--- a/foundation/eclipselink.core.test/.gitignore
+++ b/foundation/eclipselink.core.test/.gitignore
@@ -1 +1,2 @@
 /classes
+/classes/
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/PersistenceUnitProperties.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/PersistenceUnitProperties.java
index b0d6f40..75bff5f 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/PersistenceUnitProperties.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/PersistenceUnitProperties.java
@@ -35,6 +35,8 @@
  *       - 438871 : Add support for writing statement terminator character(s) when generating ddl to script.
  *     02/19/2015 - Rick Curtis  
  *       - 458877 : Add national character support
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/
 package org.eclipse.persistence.config;
 
@@ -3024,16 +3026,33 @@
 
     /**
      * The "<code>javax.persistence.query.timeout</code>" property configures
-     * the default query timeout value.
+     * the default query timeout value. Defaults to seconds, but is configurable 
+     * with PersistenceUnitProperties.QUERY_TIMEOUT_UNIT
      * <p>
      * <b>Allowed Values:</b>
      * <ul>
      * <li>a string containing a zero or greater integer value
      * </ul>
+     * @see PersistenceUnitProperties.QUERY_TIMEOUT_UNIT
      */
     public static final String QUERY_TIMEOUT = "javax.persistence.query.timeout";
 
     /**
+     * The "<code>eclipselink.query.timeout.unit</code>" property
+     * configures the query timeout unit value. Allows users more refinement.
+     * Used in combination with PersistenceUnitProperties.QUERY_TIMEOUT
+     * <p>
+     * <b>Allowed Values:</b>
+     * <ul>
+     * <li>"<code>java.util.concurrent.TimeUnit.MILLISECONDS</code>",
+     * <li>"<code>java.util.concurrent.TimeUnit.SECONDS</code>" (DEFAULT),
+     * <li>"<code>java.util.concurrent.TimeUnit.MINUTES</code>".
+     * </ul>
+     * @see PersistenceUnitProperties.QUERY_TIMEOUT
+     */
+    public static final String QUERY_TIMEOUT_UNIT = "eclipselink.query.timeout.unit";
+
+    /**
      * The "<code>eclipselink.persistence-context.close-on-commit</code>"
      * property specifies that the EntityManager will be closed or not used
      * after commit (not extended). In general this is normally always the case
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/QueryHints.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/QueryHints.java
index 49b714d..d3f9ab2 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/QueryHints.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/QueryHints.java
@@ -15,6 +15,8 @@
  *       - 325167: Make reserved # bind parameter char generic to enable native SQL pass through

  *     06/30/2011-2.3.1 Guy Pelletier 

  *       - 341940: Add disable/enable allowing native queries    

+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  

 package org.eclipse.persistence.config;

 

@@ -348,6 +350,28 @@
     public static final String JDBC_TIMEOUT = "eclipselink.jdbc.timeout";

     

     /**

+     * "javax.persistence.query.timeout" 
+     * <p>Configures the default query timeout value per the JPA specification.
+     * Valid values are strings containing a zero or greater integer value
+     * Defaults to use seconds as the unit of time.
+     * @see org.eclipse.persistence.queries.DatabaseQuery#setQueryTimeout(int)
+     */
+    public static final String QUERY_TIMEOUT = "javax.persistence.query.timeout";
+
+    /**
+     * "eclipselink.jdbc.timeout.unit"
+     * <p>Configures the query timeout unit value. Allows users more refinement.
+     * <b>Valid Values:</b>
+     * <ul>
+     * <li>"<code>java.util.concurrent.TimeUnit.MILLISECONDS</code>",
+     * <li>"<code>java.util.concurrent.TimeUnit.SECONDS</code>" (DEFAULT),
+     * <li>"<code>java.util.concurrent.TimeUnit.MINUTES</code>".
+     * </ul>
+     * @see org.eclipse.persistence.queries.DatabaseQuery#setQueryTimeoutUnit(TimeUnit)
+     */
+    public static final String QUERY_TIMEOUT_UNIT = "eclipselink.query.timeout.unit";
+
+    /**
      * "eclipselink.jdbc.fetch-size"

      * <p>Configures the JDBC fetch-size for the queries result-set.

      * This can improve the performance for queries that return large result-sets.

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorQueryManager.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorQueryManager.java
index 57c12d7..b1a427f 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorQueryManager.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorQueryManager.java
@@ -21,6 +21,8 @@
  *       - 356197: Add new VPD type to MultitenantType

  *     08/01/2012-2.5 Chris Delahunt

  *       - 371950: JPA Metadata caching

+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/

 package org.eclipse.persistence.descriptors;

 

@@ -33,6 +35,7 @@
 import java.util.List;

 import java.util.Map;

 import java.util.Vector;

+import java.util.concurrent.TimeUnit;
 import org.eclipse.persistence.exceptions.ConversionException;

 import org.eclipse.persistence.exceptions.DescriptorException;

 import org.eclipse.persistence.expressions.Expression;

@@ -124,6 +127,9 @@
     public static final int DefaultTimeout = -1;

     protected int queryTimeout;

 

+    public static final TimeUnit DefaultTimeoutUnit = TimeUnit.SECONDS;
+    protected TimeUnit queryTimeoutUnit;
+
     /**

      * INTERNAL:

      * Initialize the state of the descriptor query manager

@@ -132,6 +138,7 @@
         this.queries = new LinkedHashMap(5);

         setDoesExistQuery(new DoesExistQuery());// Always has a does exist.

         this.setQueryTimeout(DefaultTimeout);

+        this.setQueryTimeoutUnit(DefaultTimeoutUnit);
     }

 

     /**

@@ -889,6 +896,11 @@
                 setQueryTimeout(this.getParentDescriptorQueryManager().getQueryTimeout());

             }

         }

+        if (getQueryTimeoutUnit().equals(DefaultTimeoutUnit)) {
+            if (getDescriptor().hasInheritance() && (this.getDescriptor().getInheritancePolicy().getParentDescriptor() != null)) {
+                setQueryTimeoutUnit(this.getParentDescriptorQueryManager().getQueryTimeoutUnit());
+            }
+        }
 

         //if I have DefaultTimeout (via parent or not), set to NoTimeout

         if (getQueryTimeout() == DefaultTimeout) {

@@ -1686,6 +1698,10 @@
         return queryTimeout;

     }

 

+    public TimeUnit getQueryTimeoutUnit() {
+        return queryTimeoutUnit;
+    }
+
     /**

      * PUBLIC:

      * Set the number of seconds that queries will wait for their Statement to execute.

@@ -1699,6 +1715,10 @@
         this.queryTimeout = queryTimeout;

     }

 

+    public void setQueryTimeoutUnit(TimeUnit queryTimeoutUnit) {
+        this.queryTimeoutUnit = queryTimeoutUnit;
+    }
+
     /**

      * INTERNAL:

      * Returns the collection of cached Update calls.

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabaseCall.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabaseCall.java
index ea6c308..90d6120 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabaseCall.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabaseCall.java
@@ -19,12 +19,15 @@
  *       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
  *     09/27/2012-2.5 Guy Pelletier
  *       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  
 package org.eclipse.persistence.internal.databaseaccess;
 
 import java.util.*;
 import java.sql.*;
 import java.io.*;
+import java.util.concurrent.*;
 import org.eclipse.persistence.internal.helper.*;
 import org.eclipse.persistence.sessions.DatabaseRecord;
 import org.eclipse.persistence.queries.*;
@@ -103,6 +106,9 @@
     //query timeout limit in seconds
     protected int queryTimeout;
 
+    //query timeout unit
+    protected TimeUnit queryTimeoutUnit;
+
     //max rows returned in the result set by the call
     protected int maxRows;
 
@@ -161,6 +167,7 @@
         this.shouldCacheStatement = null;
         this.isFieldMatchingRequired = false;
         this.queryTimeout = 0;
+        this.queryTimeoutUnit = null;
         this.maxRows = 0;
         this.resultSetFetchSize = 0;
         this.isCursorOutputProcedure = false;
@@ -778,8 +785,18 @@
         Statement statement = accessor.prepareStatement(this, session);
 
         // Setup the max rows returned and query timeout limit.
-        if (this.queryTimeout > 0) { 
-            statement.setQueryTimeout(this.queryTimeout); 
+        if (this.queryTimeout > 0 && this.queryTimeoutUnit != null) {
+            long timeout = TimeUnit.SECONDS.convert(this.queryTimeout, this.queryTimeoutUnit);
+
+            if(timeout > Integer.MAX_VALUE){
+                timeout = Integer.MAX_VALUE;
+            }
+
+            //Round up the timeout if SECONDS are larger than the given units
+            if(TimeUnit.SECONDS.compareTo(this.queryTimeoutUnit) > 0 && this.queryTimeout % 1000 > 0){
+                timeout += 1;
+            }
+            statement.setQueryTimeout((int)timeout);
         } 
         if (!this.ignoreMaxResultsSetting && this.maxRows > 0) { 
             statement.setMaxRows(this.maxRows); 
@@ -914,6 +931,13 @@
     }
 
     /**
+     * set query timeout limit unit to the JDBC Statement
+     */
+    public void setQueryTimeoutUnit(TimeUnit queryTimeoutUnit) {
+        this.queryTimeoutUnit = queryTimeoutUnit;
+    }
+
+    /**
      * The result set is stored for the return value of cursor selects.
      */
     public void setResult(ResultSet result) {
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/CallQueryMechanism.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/CallQueryMechanism.java
index d02ccbc..a85119c 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/CallQueryMechanism.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/CallQueryMechanism.java
@@ -13,6 +13,8 @@
  *       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls

  *     08/24/2012-2.5 Guy Pelletier 

  *       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls

+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  

 package org.eclipse.persistence.internal.queries;

 

@@ -148,6 +150,7 @@
             call.setShouldCacheStatement(this.query.shouldCacheStatement());

         }

         call.setQueryTimeout(this.query.getQueryTimeout());

+        call.setQueryTimeoutUnit(this.query.getQueryTimeoutUnit());
         if (this.query.isNativeConnectionRequired()) {

             call.setIsNativeConnectionRequired(true);

         }

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/AbstractSession.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/AbstractSession.java
index c1e341a..c37793c 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/AbstractSession.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/AbstractSession.java
@@ -25,6 +25,8 @@
  *       - 395406: Fix nightly static weave test errors
  *     08/11/2014-2.5 Rick Curtis 
  *       - 440594: Tolerate invalid NamedQuery at EntityManager creation.
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/
 package org.eclipse.persistence.internal.sessions;
 
@@ -43,6 +45,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
+import java.util.concurrent.TimeUnit;
 
 import org.eclipse.persistence.config.PersistenceUnitProperties;
 import org.eclipse.persistence.config.ReferenceMode;
@@ -292,6 +295,8 @@
 
     protected int queryTimeoutDefault;
     
+    protected TimeUnit queryTimeoutUnitDefault;
+
     /** Allow a session to enable concurrent processing. */
     protected boolean isConcurrent;
     
@@ -347,6 +352,7 @@
      */
     protected AbstractSession() {
         this.name = "";
+        this.queryTimeoutUnitDefault = DescriptorQueryManager.DefaultTimeoutUnit;
         initializeIdentityMapAccessor();
         // PERF - move to lazy init (3286091)
     }
@@ -2288,6 +2294,10 @@
         return queryTimeoutDefault;
     }
 
+    public TimeUnit getQueryTimeoutUnitDefault() {
+        return queryTimeoutUnitDefault;
+    }
+
     public EntityListenerInjectionManager getEntityListenerInjectionManager() {
         if (entityListenerInjectionManager == null){
             entityListenerInjectionManager = createEntityListenerInjectionManager(this.getProperty(PersistenceUnitProperties.CDI_BEANMANAGER));
@@ -4029,6 +4039,11 @@
         this.queryTimeoutDefault = queryTimeoutDefault;
     }
 
+    @Override
+    public void setQueryTimeoutUnitDefault(TimeUnit queryTimeoutUnitDefault) {
+        this.queryTimeoutUnitDefault = queryTimeoutUnitDefault;
+    }
+
     /**
      * PUBLIC:
      * Set the profiler for the session.
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/DatabaseSessionImpl.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/DatabaseSessionImpl.java
index 36e6fda..8891fe9 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/DatabaseSessionImpl.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/DatabaseSessionImpl.java
@@ -23,6 +23,8 @@
  *       - 462586 : Add national character support for z/OS.

  *     04/14/2015 - Will Dazey
  *       - 464641 : Fixed platform matching returning CNF.
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  *       ******************************************************************************/  

 package org.eclipse.persistence.internal.sessions;

 

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/PropertiesHandler.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/PropertiesHandler.java
index 8ee04a3..186fbe2 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/PropertiesHandler.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/PropertiesHandler.java
@@ -14,12 +14,15 @@
  *     Rick Curtis - Add support for WebSphere Liberty platform.

  *     08/11/2014-2.5 Rick Curtis 

  *       - 440594: Tolerate invalid NamedQuery at EntityManager creation.

+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  

 package org.eclipse.persistence.internal.sessions;

 

 import java.util.HashMap;

 import java.util.Iterator;

 import java.util.Map;

+import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;

 import java.security.AccessController;

 import java.security.PrivilegedAction;

@@ -36,6 +39,7 @@
 import org.eclipse.persistence.config.ReferenceMode;
 import org.eclipse.persistence.config.TargetDatabase;
 import org.eclipse.persistence.config.TargetServer;
+import org.eclipse.persistence.descriptors.DescriptorQueryManager;
 import org.eclipse.persistence.internal.localization.ExceptionLocalization;

 import org.eclipse.persistence.logging.SessionLog;

 import org.eclipse.persistence.queries.ObjectLevelReadQuery;

@@ -214,6 +218,8 @@
             addProp(new BooleanProp(PersistenceUnitProperties.JPQL_TOLERATE, "false"));

             addProp(new BooleanProp(PersistenceUnitProperties.MULTITENANT_SHARED_CACHE, "false"));
             addProp(new BooleanProp(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, "true"));
+            //Enhancement
+            addProp(new QueryTimeoutUnitProp());
         }

         

         Prop(String name) {

@@ -667,4 +673,15 @@
             };

         }

     }

+
+    protected static class QueryTimeoutUnitProp extends Prop {
+        QueryTimeoutUnitProp() {
+            super(PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, DescriptorQueryManager.DefaultTimeoutUnit.toString());
+            valueArray = new Object[] {
+                TimeUnit.MILLISECONDS.toString(),
+                TimeUnit.SECONDS.toString(),
+                TimeUnit.MINUTES.toString()
+            };
+        }
+    }
 }

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkImpl.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkImpl.java
index 6b99677..0662a5a 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkImpl.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkImpl.java
@@ -30,6 +30,8 @@
  *       - 376603: Provide for table per tenant support for multitenant applications
  *     08/11/2012-2.5 Guy Pelletier  
  *       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  
 package org.eclipse.persistence.internal.sessions;
 
@@ -323,6 +325,7 @@
         this.exceptionHandler = parent.exceptionHandler;
         this.pessimisticLockTimeoutDefault = parent.pessimisticLockTimeoutDefault;
         this.queryTimeoutDefault = parent.queryTimeoutDefault;
+        this.queryTimeoutUnitDefault = parent.queryTimeoutUnitDefault;
         this.shouldOptimizeResultSetAccess = parent.shouldOptimizeResultSetAccess;
         this.serializer = parent.serializer;
         this.isConcurrent = parent.isConcurrent;
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DatabaseQuery.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DatabaseQuery.java
index 060515d..da06cf7 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DatabaseQuery.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DatabaseQuery.java
@@ -29,11 +29,15 @@
  *       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.

  *     08/11/2014-2.5 Rick Curtis 

  *       - 440594: Tolerate invalid NamedQuery at EntityManager creation.

+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/

 package org.eclipse.persistence.queries;

 

 import java.util.*;

+import java.util.concurrent.TimeUnit;
 import java.io.*;

+
 import org.eclipse.persistence.internal.helper.*;

 import org.eclipse.persistence.config.ParameterDelimiterType;

 import org.eclipse.persistence.descriptors.ClassDescriptor;

@@ -259,6 +263,8 @@
      */

     protected int queryTimeout;

 

+    protected TimeUnit queryTimeoutUnit;
+
     /* Used as default for read, means shallow write for modify. */

     public static final int NoCascading = 1;

 

@@ -339,6 +345,7 @@
         this.isPrepared = false;

         this.shouldUseWrapperPolicy = true;

         this.queryTimeout = DescriptorQueryManager.DefaultTimeout;

+        this.queryTimeoutUnit = DescriptorQueryManager.DefaultTimeoutUnit;
         this.shouldPrepare = true;

         this.shouldCloneCall = false;

         this.shouldBindAllParameters = null;

@@ -1246,6 +1253,16 @@
     }

 

     /**

+     * PUBLIC: Return the unit of time the driver will wait for a Statement to
+     * execute.
+     * 
+     * @see DescriptorQueryManager#getQueryTimeoutUnit()
+     */
+    public TimeUnit getQueryTimeoutUnit() {
+        return queryTimeoutUnit;
+    }
+
+    /**
      * INTERNAL: Returns the specific default redirector for this query type.

      * There are numerous default query redirectors. See ClassDescriptor for

      * their types.

@@ -1818,6 +1835,10 @@
         if (this.queryTimeout == DescriptorQueryManager.DefaultTimeout) {

             if (this.descriptor == null) {

                 setQueryTimeout(this.session.getQueryTimeoutDefault());

+                if(this.session.getQueryTimeoutUnitDefault() == null){
+                    this.session.setQueryTimeoutUnitDefault(DescriptorQueryManager.DefaultTimeoutUnit);
+                }
+                setQueryTimeoutUnit(this.session.getQueryTimeoutUnitDefault());
             } else {

                 int timeout = this.descriptor.getQueryManager().getQueryTimeout();

                 // No timeout means none set, so use the session default.

@@ -1825,6 +1846,13 @@
                     timeout = this.session.getQueryTimeoutDefault();

                 }

                 setQueryTimeout(timeout);

+                
+                //Bug #456067
+                TimeUnit timeoutUnit = this.descriptor.getQueryManager().getQueryTimeoutUnit();
+                if(timeoutUnit == DescriptorQueryManager.DefaultTimeoutUnit){
+                    timeoutUnit = this.session.getQueryTimeoutUnitDefault();
+                }
+                setQueryTimeoutUnit(timeoutUnit);
             }

         }

 

@@ -2277,6 +2305,11 @@
         this.shouldCloneCall = true;

     }

 

+    public void setQueryTimeoutUnit(TimeUnit queryTimeoutUnit) {
+        this.queryTimeoutUnit = queryTimeoutUnit;
+        this.shouldCloneCall = true;
+    }
+
     /**

      * PUBLIC: Set the query redirector. A redirector can be used in a query to

      * replace its execution with the execution of code. This can be used for

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/Session.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/Session.java
index ab370e8..18688e6 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/Session.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/Session.java
@@ -9,11 +9,15 @@
  *

  * Contributors:

  *     Oracle - initial API and implementation from Oracle TopLink

+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  

 package org.eclipse.persistence.sessions;

 

 import java.util.*;

+import java.util.concurrent.TimeUnit;
 import java.io.*;

+
 import org.eclipse.persistence.config.ReferenceMode;

 import org.eclipse.persistence.core.sessions.CoreSession;

 import org.eclipse.persistence.descriptors.ClassDescriptor;

@@ -999,6 +1003,14 @@
     

     /**

      * PUBLIC:

+     * Set the default query timeout units for this session.
+     * This timeout unit will apply to any queries that do not have a unit value set,
+     * and that do not have a default timeout unit defined in their descriptor.
+     */
+    public void setQueryTimeoutUnitDefault(TimeUnit queryTimeoutDefault);
+
+    /**
+     * PUBLIC:
      * Return the session's partitioning policy.

      */

     public PartitioningPolicy getPartitioningPolicy();

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/factories/ProjectClassGenerator.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/factories/ProjectClassGenerator.java
index e25e8bf..0adf552 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/factories/ProjectClassGenerator.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/factories/ProjectClassGenerator.java
@@ -11,6 +11,8 @@
  *     Oracle - initial API and implementation from Oracle TopLink
  *     11/10/2011-2.4 Guy Pelletier
  *       - 357474: Address primaryKey option from tenant discriminator column
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/
 package org.eclipse.persistence.sessions.factories;

 

@@ -830,6 +832,9 @@
         if (descriptor.getQueryManager().getQueryTimeout() != DescriptorQueryManager.DefaultTimeout) {

             method.addLine("descriptor.getQueryManager().setQueryTimeout(" + descriptor.getQueryManager().getQueryTimeout() + ");");

         }

+        if (!descriptor.getQueryManager().getQueryTimeoutUnit().equals(DescriptorQueryManager.DefaultTimeoutUnit)) {
+            method.addLine("descriptor.getQueryManager().setQueryTimeoutUnit(" + descriptor.getQueryManager().getQueryTimeoutUnit() + ");");
+        }
 

         // Custom SQL.

         if (descriptor.getQueryManager().hasReadObjectQuery() && descriptor.getQueryManager().getReadObjectQuery().isSQLCallQuery()) {

diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/server/ClientSession.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/server/ClientSession.java
index a47585b..981a108 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/server/ClientSession.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/server/ClientSession.java
@@ -16,6 +16,8 @@
  *       - 376603: Provide for table per tenant support for multitenant applications

  *     08/11/2012-2.5 Guy Pelletier  

  *       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.

+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  

 package org.eclipse.persistence.sessions.server;

 

@@ -111,6 +113,7 @@
         this.exceptionHandler = parent.getExceptionHandler();

         this.pessimisticLockTimeoutDefault = parent.getPessimisticLockTimeoutDefault();

         this.queryTimeoutDefault = parent.getQueryTimeoutDefault();

+        this.queryTimeoutUnitDefault = parent.getQueryTimeoutUnitDefault();
         this.isConcurrent = parent.isConcurrent();

         this.shouldOptimizeResultSetAccess = parent.shouldOptimizeResultSetAccess();

         this.properties = properties;

diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/query/TestQueryHints.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/query/TestQueryHints.java
index 6504a04..5e198c3 100644
--- a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/query/TestQueryHints.java
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/query/TestQueryHints.java
@@ -10,6 +10,8 @@
  * Contributors:
  *     06/30/2015-2.6.0 Will Dazey
  *       - 471487: Added test for QueryHints.JDBC_TIMEOUT that checks the executed sql statement
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added tests to check query timeout units
  ******************************************************************************/
 package org.eclipse.persistence.jpa.test.query;
 
@@ -20,6 +22,7 @@
 import java.sql.PreparedStatement;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
@@ -32,6 +35,7 @@
 import org.eclipse.persistence.jpa.test.framework.Emf;
 import org.eclipse.persistence.jpa.test.framework.EmfRunner;
 import org.eclipse.persistence.jpa.test.framework.PUPropertiesProvider;
+import org.eclipse.persistence.jpa.test.framework.Property;
 import org.eclipse.persistence.sessions.Connector;
 import org.eclipse.persistence.sessions.DatabaseLogin;
 import org.eclipse.persistence.sessions.Session;
@@ -46,9 +50,16 @@
 
     private static int setTimeout;
 
-    @Emf(classes = { Employee.class })
+    private final static int realTimeout = 3099;
+
+    @Emf(name = "defaultEMF", classes = { Employee.class } )
     private EntityManagerFactory emf;
 
+    @Emf(name = "TimeoutPropertiesEMF", classes = { Employee.class }, properties = { 
+            @Property(name = PersistenceUnitProperties.QUERY_TIMEOUT, value = "" + TestQueryHints.realTimeout),
+            @Property(name = PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, value = "MINUTES") })
+    private EntityManagerFactory emfTimeoutProperties;
+
     /**
      * Test that setting the Query Hint: QueryHints.JDBC_TIMEOUT sets the
      * timeout accordingly on the executed java.sql.Statement.
@@ -64,13 +75,11 @@
         try {
             em = emf.createEntityManager();
 
-            int queryTimeout = 3000;
-
             em.getTransaction().begin();
-            Query q = em.createQuery("SELECT x FROM Employee x").setHint(QueryHints.JDBC_TIMEOUT, queryTimeout);
+            Query q = em.createQuery("SELECT x FROM Employee x").setHint(QueryHints.JDBC_TIMEOUT, TestQueryHints.realTimeout);
             q.getResultList();
 
-            Assert.assertEquals(queryTimeout, TestQueryHints.setTimeout);
+            Assert.assertEquals(TestQueryHints.realTimeout, TestQueryHints.setTimeout);
 
             em.getTransaction().rollback();
         } catch (Exception e) {
@@ -82,6 +91,66 @@
         }
     }
 
+    /**
+     * Test that setting the Query Hint: QueryHints.JDBC_TIMEOUT_UNIT sets the
+     * timeout accordingly on the executed java.sql.Statement.
+     * 
+     * QueryHints.JDBC_TIMEOUT expects seconds by default.
+     * java.sql.Statement.getQueryTimeout() will return a value in seconds.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testQueryTimeoutUnit() throws Exception {
+        EntityManager em = null;
+        try {
+            em = emf.createEntityManager();
+
+            /*
+             * Default Case: Seconds
+             * Without being set, the units should be in seconds already.
+             */
+            em.getTransaction().begin();
+            Query q = em.createQuery("SELECT x FROM Employee x").setHint(QueryHints.JDBC_TIMEOUT, TestQueryHints.realTimeout);
+            q.getResultList();
+            int queryTimeoutSeconds = TestQueryHints.realTimeout;
+            Assert.assertEquals(queryTimeoutSeconds, TestQueryHints.setTimeout);
+            em.getTransaction().rollback();
+
+            /*
+             * Case 2: Minutes
+             * Setting units to Minutes, value should come back converted to Seconds
+             */
+            em.getTransaction().begin();
+            q = em.createQuery("SELECT x FROM Employee x").setHint(QueryHints.JDBC_TIMEOUT, TestQueryHints.realTimeout).setHint(QueryHints.QUERY_TIMEOUT_UNIT, TimeUnit.MINUTES.toString());
+            q.getResultList();
+            queryTimeoutSeconds = TestQueryHints.realTimeout * 60;
+            Assert.assertEquals(queryTimeoutSeconds, TestQueryHints.setTimeout);
+            em.getTransaction().rollback();
+
+            /*
+             * Case 3: Milliseconds
+             * Setting units to Milliseconds, value should come back converted to Seconds
+             */
+            em.getTransaction().begin();
+            q = em.createQuery("SELECT x FROM Employee x").setHint(QueryHints.JDBC_TIMEOUT, TestQueryHints.realTimeout).setHint(QueryHints.QUERY_TIMEOUT_UNIT, TimeUnit.MILLISECONDS.toString());
+            q.getResultList();
+            double queryTimeoutSecondsDouble = TestQueryHints.realTimeout / 1000d;
+            //if there was a remainder, it should round up
+            if(queryTimeoutSecondsDouble % 1 > 0){
+                queryTimeoutSecondsDouble += 1;
+            }
+            Assert.assertEquals((int)queryTimeoutSecondsDouble, TestQueryHints.setTimeout);
+            em.getTransaction().rollback();
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        } finally {
+            if (em != null) {
+                em.close();
+            }
+        }
+    }
+
     @Override
     public Map<String, Object> getAdditionalPersistenceProperties(String puName) {
         Map<String, Object> map = new HashMap<String, Object>();
diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/query/TestQueryProperties.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/query/TestQueryProperties.java
new file mode 100644
index 0000000..ea1a9bf
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/query/TestQueryProperties.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2015 IBM Corporation. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     06/30/2015-2.6.0 Will Dazey
+ *       - 471487: Added test for QueryHints.JDBC_TIMEOUT that checks the executed sql statement
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added tests to check query timeout units
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.test.query;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
+
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.eclipse.persistence.config.SessionCustomizer;
+import org.eclipse.persistence.jpa.test.basic.model.Employee;
+import org.eclipse.persistence.jpa.test.framework.Emf;
+import org.eclipse.persistence.jpa.test.framework.EmfRunner;
+import org.eclipse.persistence.jpa.test.framework.PUPropertiesProvider;
+import org.eclipse.persistence.jpa.test.framework.Property;
+import org.eclipse.persistence.sessions.Connector;
+import org.eclipse.persistence.sessions.DatabaseLogin;
+import org.eclipse.persistence.sessions.Session;
+import org.eclipse.persistence.sessions.SessionEvent;
+import org.eclipse.persistence.sessions.SessionEventAdapter;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(EmfRunner.class)
+public class TestQueryProperties implements PUPropertiesProvider {
+
+    private static int setTimeout;
+    
+    private final static int realTimeout = 3099;
+
+    @Emf(name = "timeoutEMF", classes = { Employee.class }, properties = { 
+            @Property(name = PersistenceUnitProperties.QUERY_TIMEOUT, value = "" + TestQueryProperties.realTimeout) })
+    private EntityManagerFactory emfTimeout;
+
+    @Emf(name = "timeoutWithUnitMintuesEMF", classes = { Employee.class }, properties = { 
+            @Property(name = PersistenceUnitProperties.QUERY_TIMEOUT, value = "" + TestQueryProperties.realTimeout),
+            @Property(name = PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, value = "MINUTES") })
+    private EntityManagerFactory emfTimeoutMinutes;
+    
+    @Emf(name = "timeoutWithUnitMillisecondsEMF", classes = { Employee.class }, properties = { 
+            @Property(name = PersistenceUnitProperties.QUERY_TIMEOUT, value = "" + TestQueryProperties.realTimeout),
+            @Property(name = PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, value = "MILLISECONDS") })
+    private EntityManagerFactory emfTimeoutMilliseconds;
+
+    /**
+     * Test that setting the property "PersistenceUnitProperties.QUERY_TIMEOUT_UNIT" sets the
+     * timeout accordingly on the executed java.sql.Statement.
+     * 
+     * Assumes value will be converted to Seconds for JDBC.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testTimeoutUnitDefault() throws Exception {
+        EntityManager em = null;
+        try {
+            em = emfTimeout.createEntityManager();
+
+            em.getTransaction().begin();
+            Query q = em.createQuery("SELECT x FROM Employee x");
+            q.getResultList();
+            
+            int queryTimeoutSeconds = TestQueryProperties.realTimeout;
+
+            Assert.assertEquals(queryTimeoutSeconds, TestQueryProperties.setTimeout);
+
+            em.getTransaction().rollback();
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        } finally {
+            if (em != null) {
+                em.close();
+            }
+        }
+    }
+
+    /**
+     * Test that setting the property "PersistenceUnitProperties.QUERY_TIMEOUT_UNIT" sets the
+     * timeout accordingly on the executed java.sql.Statement.
+     * 
+     * Assumes value will be converted to Seconds for JDBC.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testTimeoutUnitMinutes() throws Exception {
+        EntityManager em = null;
+        try {
+            em = emfTimeoutMinutes.createEntityManager();
+
+            em.getTransaction().begin();
+            Query q = em.createQuery("SELECT x FROM Employee x");
+            q.getResultList();
+            
+            int queryTimeoutSeconds = TestQueryProperties.realTimeout * 60;
+
+            Assert.assertEquals(queryTimeoutSeconds, TestQueryProperties.setTimeout);
+
+            em.getTransaction().rollback();
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        } finally {
+            if (em != null) {
+                em.close();
+            }
+        }
+    }
+
+    /**
+     * Test that setting the property "PersistenceUnitProperties.QUERY_TIMEOUT_UNIT" sets the
+     * timeout accordingly on the executed java.sql.Statement.
+     * 
+     * Assumes value will be converted to Seconds for JDBC.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void testTimeoutUnitMilliseconds() throws Exception {
+        EntityManager em = null;
+        try {
+            em = emfTimeoutMilliseconds.createEntityManager();
+
+            em.getTransaction().begin();
+            Query q = em.createQuery("SELECT x FROM Employee x");
+            q.getResultList();
+            
+            double queryTimeoutSeconds = TestQueryProperties.realTimeout / 1000d;
+            //if there was a remainder, it should round up
+            if(queryTimeoutSeconds % 1 > 0){
+                queryTimeoutSeconds += 1;
+            }
+
+            Assert.assertEquals((int)queryTimeoutSeconds, TestQueryProperties.setTimeout);
+
+            em.getTransaction().rollback();
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        } finally {
+            if (em != null) {
+                em.close();
+            }
+        }
+    }
+
+    @Override
+    public Map<String, Object> getAdditionalPersistenceProperties(String puName) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, Customizer.class.getName());
+        return map;
+    }
+
+    public static class Customizer implements SessionCustomizer {
+        @Override
+        public void customize(Session session) throws Exception {
+            session.getEventManager().addListener(new SessionEventAdapter() {
+                @Override
+                public void preLogin(SessionEvent event) {
+                    DatabaseLogin login = event.getSession().getLogin();
+                    login.setConnector(ConnectorInvocationHandler.createStatementProxy(login.getConnector()));
+                }
+            });
+        }
+    }
+
+    public static class ConnectorInvocationHandler implements InvocationHandler {
+        private Connector wrappedConnector;
+
+        public ConnectorInvocationHandler(Connector stmt) {
+            wrappedConnector = stmt;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (method.getName().equals("connect") && proxy instanceof Connector) {
+                return ConnectionInvocationHandler.createStatementProxy((Connection) method.invoke(wrappedConnector, args));
+            }
+            return method.invoke(wrappedConnector, args);
+        }
+
+        public static Connector createStatementProxy(Connector toWrap) {
+            return (Connector) Proxy.newProxyInstance(Connector.class.getClassLoader(), new Class[] { Connector.class }, new ConnectorInvocationHandler(toWrap));
+        }
+    }
+
+    public static class ConnectionInvocationHandler implements InvocationHandler {
+        private Connection wrappedConnection;
+
+        public ConnectionInvocationHandler(Connection stmt) {
+            wrappedConnection = stmt;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (method.getName().equals("prepareStatement") && proxy instanceof Connection) {
+                return PreparedStatementInvocationHandler.createStatementProxy((PreparedStatement) method.invoke(wrappedConnection, args));
+            }
+            return method.invoke(wrappedConnection, args);
+        }
+
+        public static Connection createStatementProxy(Connection toWrap) {
+            return (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class[] { Connection.class }, new ConnectionInvocationHandler(toWrap));
+        }
+    }
+
+    public static class PreparedStatementInvocationHandler implements InvocationHandler {
+        private PreparedStatement wrappedStatement;
+
+        public PreparedStatementInvocationHandler(PreparedStatement stmt) {
+            wrappedStatement = stmt;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (method.getName().equals("setQueryTimeout") && proxy instanceof PreparedStatement) {
+                if (args.length > 0) {
+                    TestQueryProperties.setTimeout = (Integer) args[0];
+                }
+            }
+            return method.invoke(wrappedStatement, args);
+        }
+
+        public static PreparedStatement createStatementProxy(PreparedStatement toWrap) {
+            return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(), new Class[] { PreparedStatement.class }, new PreparedStatementInvocationHandler(toWrap));
+        }
+    }
+}
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerSetupImpl.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerSetupImpl.java
index 02a6ed6..a9da2fe 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerSetupImpl.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerSetupImpl.java
@@ -60,6 +60,8 @@
  *       - 458877 : Add national character support
  *     03/04/2015 - Will Dazey 
  *       - 460862 : Added support for JTA schema generation without JTA-DS
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  *****************************************************************************/  
 package org.eclipse.persistence.internal.jpa;
 
@@ -125,6 +127,7 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
 
 import javax.persistence.OptimisticLockException;
 import javax.persistence.PersistenceException;
@@ -2769,6 +2772,7 @@
             updateIdValidation(m);
             updatePessimisticLockTimeout(m);
             updateQueryTimeout(m);
+            updateQueryTimeoutUnit(m);
             if (!session.hasBroker()) {
                 updateCacheCoordination(m, loader);
             }
@@ -3494,7 +3498,6 @@
 
     private void updateQueryTimeout(Map persistenceProperties) {
         String timeout = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.QUERY_TIMEOUT, persistenceProperties, session);
-
         try {
             if (timeout != null) {
                 session.setQueryTimeoutDefault(Integer.parseInt(timeout));
@@ -3504,6 +3507,19 @@
         }
     }
 
+    //Bug #456067: Added persistence unit support for timeout units
+    private void updateQueryTimeoutUnit(Map persistenceProperties) {
+        String timeoutUnit = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, persistenceProperties, session);
+        try {
+            if (timeoutUnit != null) {
+                TimeUnit unit = TimeUnit.valueOf(timeoutUnit);
+                session.setQueryTimeoutUnitDefault(unit);
+            }
+        } catch (IllegalArgumentException exception) {
+            this.session.handleException(ValidationException.invalidValueForProperty(timeoutUnit, PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, exception));
+        }
+    }
+
     /**
      * If Bean Validation is enabled, bootstraps Bean Validation on descriptors.
      * @param puProperties merged properties for this persistence unit
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/QueryHintsHandler.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/QueryHintsHandler.java
index 0513f95..73dc13f 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/QueryHintsHandler.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/QueryHintsHandler.java
@@ -19,6 +19,8 @@
  *       - 341940: Add disable/enable allowing native queries 

  *     06/30/2015-2.6.0 Will Dazey
  *       - 471487: Fixed eclipselink.jdbc.timeout hint not applying correctly to SQLCall
+ *     09/03/2015 - Will Dazey
+ *       - 456067 : Added support for defining query timeout units
  ******************************************************************************/  

 package org.eclipse.persistence.internal.jpa;

 

@@ -31,6 +33,7 @@
 import java.util.Map;

 import java.util.Set;

 import java.util.StringTokenizer;

+import java.util.concurrent.TimeUnit;
 

 import javax.persistence.CacheRetrieveMode;

 import javax.persistence.CacheStoreMode;

@@ -249,6 +252,10 @@
             addHint(new LeftFetchHint());

             addHint(new ReadOnlyHint());

             addHint(new JDBCTimeoutHint());

+            //Enhancement
+            addHint(new QueryTimeoutUnitHint());
+            //Enhancement
+            addHint(new QueryTimeoutHint());
             addHint(new JDBCFetchSizeHint());

             addHint(new JDBCMaxRowsHint());

             addHint(new JDBCFirstResultHint());

@@ -1868,6 +1875,36 @@
         }

     }

         

+    //Bug #456067: Added support for user defining the timeout units to use
+    protected static class QueryTimeoutUnitHint extends Hint {
+        QueryTimeoutUnitHint() {
+            super(QueryHints.QUERY_TIMEOUT_UNIT, "");
+        }
+
+        DatabaseQuery applyToDatabaseQuery(Object valueToApply, DatabaseQuery query, ClassLoader loader, AbstractSession activeSession) {
+            try {
+                TimeUnit unit = TimeUnit.valueOf((String)valueToApply);
+                query.setQueryTimeoutUnit(unit);
+            }
+            catch(IllegalArgumentException e) {
+                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-type-for-query-hint",new Object[]{getQueryId(query), name, getPrintValue(valueToApply)}));
+            }
+            return query;
+        }
+    }
+
+    //Bug #456067: Added support for query hint "javax.persistence.query.timeout" defined in the spec
+    protected static class QueryTimeoutHint extends Hint {
+        QueryTimeoutHint() {
+            super(QueryHints.QUERY_TIMEOUT, "");
+        }
+
+        DatabaseQuery applyToDatabaseQuery(Object valueToApply, DatabaseQuery query, ClassLoader loader, AbstractSession activeSession) {
+            query.setQueryTimeout(QueryHintsHandler.parseIntegerHint(valueToApply, QueryHints.QUERY_TIMEOUT));
+            return query;
+        }
+    }
+
     protected static class JDBCFetchSizeHint extends Hint {

         JDBCFetchSizeHint() {

             super(QueryHints.JDBC_FETCH_SIZE, "");

@@ -2064,5 +2101,4 @@
             return query;

         }

     }

-

 }