Author: ppoddar
Date: Tue Jan 24 22:26:27 2012
New Revision: 1235533

URL: http://svn.apache.org/viewvc?rev=1235533&view=rev
Log:
OPENJPA-2099: Use thread gate for reused select. Guard parameter binding

Modified:
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
    
openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
 Tue Jan 24 22:26:27 2012
@@ -644,6 +644,8 @@ public interface JDBCConfiguration
      * Sets if select statements are aggressively cached.
      * An aggressive select cache assumes that {@link FetchConfiguration fetch 
plan}
      * does not change between execution.
+     * <br>
+     * This setting can be changed once and only once.
      *  
      * @since 2.2.0
      */

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
 Tue Jan 24 22:26:27 2012
@@ -40,6 +40,7 @@ import org.apache.openjpa.jdbc.sql.Selec
 import org.apache.openjpa.jdbc.sql.SelectExecutor;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.ThreadGate;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.meta.ValueStrategies;
 import org.apache.openjpa.util.InternalException;
@@ -50,8 +51,10 @@ import org.apache.openjpa.util.UserExcep
  * Mapping for a single-valued field that delegates to a {@link ValueHandler}.
  *
  * @author Abe White
+ * @author Pinaki Poddar (select cache)
  * @since 0.4.0
  */
+@SuppressWarnings("serial")
 public class HandlerFieldStrategy
     extends AbstractFieldStrategy
     implements Joinable, Embeddable {
@@ -65,7 +68,8 @@ public class HandlerFieldStrategy
     protected Object[] _args = null;
     protected boolean _load = false;
     protected boolean _lob = false;
-    private Select    _select;
+    private Select    _executor;
+    private ThreadGate _lock = new ThreadGate();
     
     public void map(boolean adapt) {
         if (field.getHandler() == null)
@@ -222,28 +226,33 @@ public class HandlerFieldStrategy
             }
         }
         Select sel;
-        if (_select == null) {
-               sel = store.getSQLFactory().newSelect();
-               if (store.getConfiguration().getSelectCacheEnabled()) {
-                       _select = sel;
-               }
-            sel.select(_cols);
-        } else {
-               sel = _select;
-        }
-        
-        field.wherePrimaryKey(sel, sm, store);
-
-        Result res = sel.execute(store, fetch);
-        Object val = null;
         try {
-            if (res.next())
-                val = HandlerStrategies.loadDataStore(field, res, null, _cols);
+               _lock.lock();
+               if (_executor == null) {
+                       sel = store.getSQLFactory().newSelect();
+                       if (store.getConfiguration().getSelectCacheEnabled()) {
+                               _executor = sel;
+                       }
+                   sel.select(_cols);
+               } else {
+                       sel = _executor;
+               }
+               
+               field.wherePrimaryKey(sel, sm, store);
+       
+               Result res = sel.execute(store, fetch);
+               Object val = null;
+               try {
+                   if (res.next())
+                       val = HandlerStrategies.loadDataStore(field, res, null, 
_cols);
+               } finally {
+                   res.close();
+               }
+       
+               loadEmbedded(sm, store, fetch, val);
         } finally {
-            res.close();
+               _lock.unlock();
         }
-
-        loadEmbedded(sm, store, fetch, val);
     }
 
     public Object toDataStoreValue(Object val, JDBCStore store) {

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
 Tue Jan 24 22:26:27 2012
@@ -58,6 +58,7 @@ import org.apache.openjpa.jdbc.sql.Union
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.ThreadGate;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
@@ -93,6 +94,7 @@ public class RelationFieldStrategy
     private Boolean _fkOid = null;
     
     private SelectExecutor _executor;
+    private ThreadGate _lock = new ThreadGate();
     
     public void map(boolean adapt) {
         if (field.getTypeCode() != JavaTypes.PC || field.isEmbeddedPC())
@@ -775,56 +777,63 @@ public class RelationFieldStrategy
         // back to our fk table if not an inverse mapping (in which case we
         // can just make sure the inverse cols == our pk values)
         Union union;
-        if (_executor == null) {
-               union = store.getSQLFactory().newUnion(rels.length);
-            union.setExpectedResultCount(1, false);
-            if (fetch.getSubclassFetchMode(field.getTypeMapping()) != 
JDBCFetchConfiguration.EAGER_JOIN)
-                    union.abortUnion();
-            if 
(((JDBCConfiguration)field.getMappingRepository().getConfiguration()).getSelectCacheEnabled())
 {
-               _executor = union;
-            }
-        } else {
-               union = (Union)_executor;
-        }
-        union.select(new Union.Selector() {
-            public void select(Select sel, int idx) {
-               ForeignKey fk = field.getForeignKey(rels[idx]);
-               ClassMapping mapping = field.getDefiningMapping();
-               Object oid = sm.getObjectId();
-                if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
-                    sel.whereForeignKey(fk, oid, mapping, store);
-                } else {
-                    if (!field.isBidirectionalManyToOneJoinTable()) {
-                       if (sel.isReadOnly()) {
-                               resJoins[idx] = sel.getJoins();
-                       } else {
-                               resJoins[idx] = 
sel.newJoins().joinRelation(field.getName(), fk, rels[idx],
-                                subs, false, false);
-                       }
-                        field.wherePrimaryKey(sel, sm, store);
-                    } else {
-                       if (sel.isReadOnly()) {
-                               resJoins[idx] = sel.getJoins();
-                       } else { 
-                               resJoins[idx] = 
sel.newJoins().joinRelation(null, 
-                                               
field.getBidirectionalOneToManyJoinForeignKey(), rels[idx],
-                                    subs, false, false);
-                       }
-                        
sel.whereForeignKey(field.getBidirectionalOneToManyElementForeignKey(), oid, 
mapping, store);
-                    }
-                }
-                if (!sel.isReadOnly()) {
-                       sel.select(rels[idx], subs, store, fetch, 
JDBCFetchConfiguration.EAGER_JOIN, resJoins[idx]);
-                }
-            }
-        });
-
-        Result res = union.execute(store, fetch);
         try {
-            Object val = (res.next()) ? res.load(rels[res.indexOf()], store, 
fetch, resJoins[res.indexOf()]) : null;
-            sm.storeObject(field.getIndex(), val);
+               _lock.lock();
+               if (_executor == null) {
+                       union = store.getSQLFactory().newUnion(rels.length);
+                   union.setExpectedResultCount(1, false);
+                   if (fetch.getSubclassFetchMode(field.getTypeMapping()) != 
JDBCFetchConfiguration.EAGER_JOIN)
+                           union.abortUnion();
+                   if 
(((JDBCConfiguration)field.getMappingRepository().getConfiguration()).getSelectCacheEnabled())
 {
+                       _executor = union;
+                   }
+               } else {
+                       union = (Union)_executor;
+               }
+               union.select(new Union.Selector() {
+                   public void select(Select sel, int idx) {
+                       ForeignKey fk = field.getForeignKey(rels[idx]);
+                       ClassMapping mapping = field.getDefiningMapping();
+                       Object oid = sm.getObjectId();
+                       if (field.getJoinDirection() == 
FieldMapping.JOIN_INVERSE) {
+                           sel.whereForeignKey(fk, oid, mapping, store);
+                       } else {
+                           if (!field.isBidirectionalManyToOneJoinTable()) {
+                               if (sel.isReadOnly()) {
+                                       resJoins[idx] = sel.getJoins();
+                               } else {
+                                       resJoins[idx] = 
sel.newJoins().joinRelation(field.getName(), fk, rels[idx],
+                                       subs, false, false);
+                               }
+                               field.wherePrimaryKey(sel, sm, store);
+                           } else {
+                               if (sel.isReadOnly()) {
+                                       resJoins[idx] = sel.getJoins();
+                               } else { 
+                                       resJoins[idx] = 
sel.newJoins().joinRelation(null, 
+                                                       
field.getBidirectionalOneToManyJoinForeignKey(), rels[idx],
+                                           subs, false, false);
+                               }
+                               
sel.whereForeignKey(field.getBidirectionalOneToManyElementForeignKey(), 
+                                               oid, mapping, store);
+                           }
+                       }
+                       if (!sel.isReadOnly()) {
+                               sel.select(rels[idx], subs, store, fetch, 
+                                               
JDBCFetchConfiguration.EAGER_JOIN, resJoins[idx]);
+                       }
+                   }
+               });
+       
+               Result res = union.execute(store, fetch);
+               try {
+                       sm.storeObject(field.getIndex(), res.next()
+                       ? res.load(rels[res.indexOf()], store, fetch, 
resJoins[res.indexOf()]) : null);
+               } finally {
+                   res.close();
+               }
         } finally {
-            res.close();
+               _lock.unlock();
         }
     }
 

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
 Tue Jan 24 22:26:27 2012
@@ -40,10 +40,10 @@ import org.apache.openjpa.jdbc.sql.Joins
 import org.apache.openjpa.jdbc.sql.Result;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.jdbc.sql.SelectExecutor;
-import org.apache.openjpa.jdbc.sql.SelectImpl;
 import org.apache.openjpa.jdbc.sql.Union;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.StateManagerImpl;
+import org.apache.openjpa.lib.util.ThreadGate;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.util.ChangeTracker;
@@ -70,6 +70,7 @@ import org.apache.openjpa.util.Proxy;
 public abstract class StoreCollectionFieldStrategy
     extends ContainerFieldStrategy {
        protected SelectExecutor _executor;
+       protected ThreadGate _lock = new ThreadGate();
        
     /**
      * Return the foreign key used to join to the owning field for the given
@@ -165,6 +166,7 @@ public abstract class StoreCollectionFie
         else {
             final ClassMapping[] elems = getIndependentElementMappings(true);
             Union union = (Union) sel;
+            if (union.isReadOnly())
             if (fetch.getSubclassFetchMode(field.getElementMapping().
                 getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
                 union.abortUnion();
@@ -182,6 +184,7 @@ public abstract class StoreCollectionFie
         // we limit further eager fetches to joins, because after this point
         // the select has been modified such that parallel clones may produce
         // invalid sql
+       if (sel.isReadOnly()) return;
         boolean outer = field.getNullValue() != FieldMapping.NULL_EXCEPTION;
         // force inner join for inner join fetch 
         if (fetch.hasFetchInnerJoin(field.getFullName(false)))
@@ -359,8 +362,7 @@ public abstract class StoreCollectionFie
                 mappedByValue = owner.getPersistenceCapable();
                 res.setMappedByFieldMapping(mappedByFieldMapping);
                 res.setMappedByValue(mappedByValue);
-            } else if (coll instanceof Collection && 
-                ((Collection) coll).size() > 0) {
+            } else if (coll instanceof Collection && !((Collection) 
coll).isEmpty()) {
                 // Customer (1) <--> Orders(n)
                 // coll contains the values of the toMany field (Orders)
                 // get the StateManager of this toMany value
@@ -525,7 +527,11 @@ public abstract class StoreCollectionFie
             return;
         }
         // select data for this state manager
-        synchronized (this) {
+        // Select can be configured for reuse. The locking mechanics ensures 
that
+        // under reuse scenario, the Select structure is built under a thread 
gate
+        // but later usage is unguarded because a reused select is (almost) 
immutable.
+        try {
+               _lock.lock();
                final ClassMapping[] elems = 
getIndependentElementMappings(true);
                final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
                Union union;
@@ -577,6 +583,8 @@ public abstract class StoreCollectionFie
                } else {
                    sm.storeObject(field.getIndex(), coll);
                }
+        } finally {
+               _lock.unlock();
         }
     }
 
@@ -635,6 +643,7 @@ public abstract class StoreCollectionFie
         }
         return oid;
     }
+        
     
     public String toString() {
        return getClass().getSimpleName() + '[' + field.getName() + ']';

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
 Tue Jan 24 22:26:27 2012
@@ -24,13 +24,22 @@ import org.apache.openjpa.jdbc.schema.Co
 /**
  * A binding parameter in a SQL statement.
  * <br>
- * A binding parameter is used in <tt>WHERE<tt> clause. The parameter is 
identified by an
- * immutable key and has a value. The parameter is further qualified by 
whether it is
- * user specified (e.g. from a query parameter) or internally generated (e.g. 
a discriminator
- * value for inheritance join). A database column can also be optionally 
associated with 
- * a binding parameter.
+ * A binding parameter is used in <tt>WHERE</tt> clause. The parameter is 
identified by an
+ * immutable key and has a value. The value of a parameter is bound to a 
thread and hence
+ * different thread may see different value. These parameters are associated 
with a {@link Select}
+ * and they are the only mutable components of an otherwise {@link 
SelectExecutor#isReadOnly() immutable}  
+ * select. 
+ * <br><b>NOTE:</b>
+ * The primary assumption of usage is that the binding parameter values to a 
cached select and
+ * executing it are carried out in the same thread. 
+ * <br> 
+ * The parameter is further qualified by whether it is user specified (e.g. 
from a query parameter) 
+ * or internally generated (e.g. a discriminator value for inheritance join). 
A database column can 
+ * also be optionally associated with a binding parameter. Currently {@link 
SQLBuffer#bind(Object, Column)
+ * rebinding} a parameter to a value is only possible if the parameter is 
associated with a column.
  * 
  * @see SQLBuffer#appendValue(Object, Column, 
org.apache.openjpa.kernel.exps.Parameter)
+ * @see SQLBuffer#bind(Object, Column)
  * 
  * @author Pinaki Poddar
  *
@@ -42,7 +51,7 @@ public class BindParameter {
        private final Column  _column;
        // key of this parameter
        private final Object  _key;
-       private Object _value;
+       private ThreadLocal<Object> _value = new ThreadLocal<Object>();
        
        /**
         * Constructs a parameter with given key, column and user flag.
@@ -58,21 +67,21 @@ public class BindParameter {
                _key = key;
                _user = user;
                _column = column;
-               _value  = value;
+               _value.set(value);
        }
        
        /**
         * Gets the value bound to this parameter. Can be null.
         */
        public Object getValue() {
-               return _value;
+               return _value.get();
        }
        
        /**
         * Binds the given value to this parameter. Can be null.
         */
        public void setValue(Object value) {
-               _value = value;
+               _value.set(value);
        }
 
        /**

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
 Tue Jan 24 22:26:27 2012
@@ -112,6 +112,15 @@ public class LogicalUnion
         return false;
     }
 
+       @Override
+       public boolean isReadOnly() {
+               for (int i = 0; i < sels.length; i++) {
+                       if (sels[i].isReadOnly())
+                               return true;
+               }
+               return false;
+       }
+       
     public void abortUnion() {
     }
 
@@ -235,8 +244,7 @@ public class LogicalUnion
         if (getExpectedResultCount() == 1) {
             AbstractResult res;
             for (int i = 0; i < sels.length; i++) {
-                res = (AbstractResult) sels[i].execute(store, fetch,
-                    lockLevel);
+                res = (AbstractResult) sels[i].execute(store, fetch, 
lockLevel);
                 res.setBaseMapping(mappings[i]);
                 res.setIndexOf(i);
 
@@ -267,8 +275,7 @@ public class LogicalUnion
         try {
             List l;
             for (int i = 0; i < res.length; i++) {
-                res[i] = (AbstractResult) sels[i].execute(store, fetch,
-                    lockLevel);
+                res[i] = (AbstractResult) sels[i].execute(store, fetch, 
lockLevel);
                 res[i].setBaseMapping(mappings[i]);
                 res[i].setIndexOf(i);
 
@@ -999,4 +1006,5 @@ public class LogicalUnion
             return a1.length - a2.length;
         }
     }
+
 }

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
 Tue Jan 24 22:26:27 2012
@@ -776,17 +776,4 @@ public interface Select
      */
     public DBDictionary getDictionary() ; 
     
-    /**
-     * Affirms if this select is structurally immutable.
-     * A select becomes immutable upon {@link #execute(JDBCStore, 
JDBCFetchConfiguration) execution}.
-     * There is no explicit way to turn a select into read-only status.
-     * <br>
-     * The immutable contract does not prevent {@link SQLBuffer#bind(Object, 
Column) binding} 
-     * new values to {@link BindParameter parameters}.  
-     * 
-     * @return false on construction, true after execution.
-     * 
-     * @since 2.2.0
-     */
-    boolean isReadOnly();
 }

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
 Tue Jan 24 22:26:27 2012
@@ -23,6 +23,7 @@ import java.sql.SQLException;
 import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.schema.Column;
 
 /**
  * Interface for configuring and executing a SQL select.
@@ -151,4 +152,19 @@ public interface SelectExecutor {
      * @since 2.0.0
      */
     public boolean hasMultipleSelects();
+    
+    /**
+     * Affirms if this select is structurally immutable.
+     * A select becomes immutable upon {@link #execute(JDBCStore, 
JDBCFetchConfiguration) execution}.
+     * There is no explicit way to turn a select into read-only status.
+     * <br>
+     * The immutable contract does not prevent {@link SQLBuffer#bind(Object, 
Column) binding} 
+     * new values to {@link BindParameter parameters}.  
+     * 
+     * @return false on construction, true after execution.
+     * 
+     * @since 2.2.0
+     */
+    boolean isReadOnly();
+
 }

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingQuery.java
 Tue Jan 24 22:26:27 2012
@@ -271,11 +271,14 @@ public class DelegatingQuery
         }
     }
 
-    public void setCandidateType(Class cls, boolean subs) {
+    public void setCandidateType(Class<?> cls, boolean subs) {
         try {
+               lock();
             _query.setCandidateType(cls, subs);
         } catch (RuntimeException re) {
             throw translate(re);
+        } finally {
+               unlock();
         }
     }
 
@@ -289,9 +292,12 @@ public class DelegatingQuery
 
     public void setReadOnly(boolean readOnly) {
         try {
+               lock();
             _query.setReadOnly(readOnly);
         } catch (RuntimeException re) {
             throw translate(re);
+        } finally {
+               unlock();
         }
     }
 

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
 Tue Jan 24 22:26:27 2012
@@ -58,11 +58,11 @@ import org.apache.openjpa.conf.OpenJPACo
 public class ImplHelper {
 
     // Cache for from/to type assignments
-    private static final Map _assignableTypes =
+    private static final Map<Class<?>,Map<?,?>> _assignableTypes =
         new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);
 
     // map of all new unenhanced instances active in this classloader
-    public static final Map _unenhancedInstanceMap =
+    public static final Map<Object,PersistenceCapable> _unenhancedInstanceMap =
         new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD) {
 
             protected boolean eq(Object x, Object y) {
@@ -91,13 +91,13 @@ public class ImplHelper {
      * @see StoreManager#loadAll
      * @since 0.4.0
      */
-    public static Collection loadAll(Collection sms, StoreManager store,
+    public static Collection<Object> loadAll(Collection<OpenJPAStateManager> 
sms, StoreManager store,
         PCState state, int load, FetchConfiguration fetch, Object context) {
-        Collection failed = null;
+        Collection<Object> failed = null;
         OpenJPAStateManager sm;
         LockManager lm;
-        for (Iterator itr = sms.iterator(); itr.hasNext();) {
-            sm = (OpenJPAStateManager) itr.next();
+        for (Iterator<OpenJPAStateManager> itr = sms.iterator(); 
itr.hasNext();) {
+            sm = itr.next();
             if (sm.getManagedInstance() == null) {
                 if (!store.initialize(sm, state, fetch, context))
                     failed = addFailedId(sm, failed);
@@ -110,23 +110,23 @@ public class ImplHelper {
             } else if (!store.exists(sm, context))
                 failed = addFailedId(sm, failed);
         }
-        return (failed == null) ? Collections.EMPTY_LIST : failed;
+        if (failed == null) return Collections.emptyList();
+        return failed;
     }
 
     /**
      * Add identity of given instance to collection.
      */
-    private static Collection addFailedId(OpenJPAStateManager sm,
-        Collection failed) {
+    private static Collection<Object> addFailedId(OpenJPAStateManager sm, 
Collection<Object> failed) {
         if (failed == null)
-            failed = new ArrayList();
+            failed = new ArrayList<Object>();
         failed.add(sm.getId());
         return failed;
     }
 
     /**
      * Generate a value for the given metadata, or return null. Generates
-     * values for hte following strategies: {@link ValueStrategies#SEQUENCE},
+     * values for the following strategies: {@link ValueStrategies#SEQUENCE},
      * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
      */
     public static Object generateIdentityValue(StoreContext ctx,
@@ -136,7 +136,7 @@ public class ImplHelper {
 
     /**
      * Generate a value for the given metadata, or return null. Generates
-     * values for hte following strategies: {@link ValueStrategies#SEQUENCE},
+     * values for the following strategies: {@link ValueStrategies#SEQUENCE},
      * {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
      */
     public static Object generateFieldValue(StoreContext ctx,
@@ -218,11 +218,9 @@ public class ImplHelper {
      *
      * @since 1.0.0
      */
-    public static boolean isManagedType(OpenJPAConfiguration conf, Class type) 
{
-        return (PersistenceCapable.class.isAssignableFrom(type)
-            || (type != null
-                && (conf == null || conf.getRuntimeUnenhancedClassesConstant()
-                    == RuntimeUnenhancedClassesModes.SUPPORTED)
+    public static boolean isManagedType(OpenJPAConfiguration conf, Class<?> 
type) {
+        return (type != null && PersistenceCapable.class.isAssignableFrom(type)
+            || ((conf == null || conf.getRuntimeUnenhancedClassesConstant()== 
RuntimeUnenhancedClassesModes.SUPPORTED)
                 && PCRegistry.isRegistered(type)));
     }
 
@@ -246,7 +244,7 @@ public class ImplHelper {
      * @param to second class instance to be checked for assignability
      * @return true if the "to" class is assignable to the "from" class
      */
-    public static boolean isAssignable(Class from, Class to) {
+    public static boolean isAssignable(Class<?> from, Class<?> to) {
         if (from == null || to == null)
             return false;
 
@@ -308,8 +306,7 @@ public class ImplHelper {
         }
     }
 
-    public static void registerPersistenceCapable(
-        ReflectingPersistenceCapable pc) {
+    public static void registerPersistenceCapable(ReflectingPersistenceCapable 
pc) {
         _unenhancedInstanceMap.put(pc.getManagedInstance(), pc);
     }
 

Modified: 
openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java
 (original)
+++ 
openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestGate.java
 Tue Jan 24 22:26:27 2012
@@ -66,7 +66,7 @@ public class TestGate extends TestCase {
                        };
                        futures.add(threadPool.submit(r));
                }
-               
+               Thread.sleep(THREAD_TIME*10);
                for (Future<?> f : futures) {
                        try {
                                f.get();

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java?rev=1235533&r1=1235532&r2=1235533&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
 Tue Jan 24 22:26:27 2012
@@ -87,22 +87,22 @@ public interface OpenJPAQuery<X> extends
      * Return the candidate collection, or <code>null</code> if an
      * extent was specified instead of a collection.
      */
-    public Collection getCandidateCollection();
+    public Collection<?> getCandidateCollection();
 
     /**
      * Set a collection of candidates.
      */
-    public OpenJPAQuery<X> setCandidateCollection(Collection coll);
+    public OpenJPAQuery<X> setCandidateCollection(Collection<?> coll);
 
     /**
      * Query result element type.
      */
-    public Class getResultClass();
+    public Class<?> getResultClass();
 
     /**
      * Query result element type.
      */
-    public OpenJPAQuery<X> setResultClass(Class type);
+    public OpenJPAQuery<X> setResultClass(Class<?> type);
 
     /**
      * Whether subclasses are included in the query results.
@@ -150,7 +150,7 @@ public interface OpenJPAQuery<X> extends
     /**
      * Set parameters.
      */
-    public OpenJPAQuery<X> setParameters(Map params);
+    public OpenJPAQuery<X> setParameters(Map<?,?> params);
 
     /**
      * Set parameters.
@@ -169,7 +169,7 @@ public interface OpenJPAQuery<X> extends
      *
      * @param params the named parameter map for the query invocation
      */
-    public String[] getDataStoreActions(Map params);
+    public String[] getDataStoreActions(Map<?,?> params);
 
     public OpenJPAQuery<X> setMaxResults(int maxResult);
 
@@ -207,7 +207,7 @@ public interface OpenJPAQuery<X> extends
      * Gets whether the type of user-supplied bind parameter value and the 
type of target persistent 
      * property they bind to are checked with strong or weak constraint.
      * 
-     * @return the booelan state. False by default, i.e. the type of a bind 
parameter value is checked
+     * @return the boolean state. False by default, i.e. the type of a bind 
parameter value is checked
      * strongly against the target property type.  
      */
     public boolean getRelaxBindParameterTypeChecking();

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=1235533&r1=1235532&r2=1235533&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
 Tue Jan 24 22:26:27 2012
@@ -213,14 +213,14 @@ public class QueryImpl<X> extends Abstra
                return this;
        }
 
-       public Class getResultClass() {
-               Class res = _query.getResultType();
+       public Class<?> getResultClass() {
+               Class<?> res = _query.getResultType();
                if (res != null)
                        return res;
                return _query.getCandidateType();
        }
 
-       public OpenJPAQuery<X> setResultClass(Class cls) {
+       public OpenJPAQuery<X> setResultClass(Class<?> cls) {
                _em.assertNotCloseInvoked();
                if (ImplHelper.isManagedType(_em.getConfiguration(), cls))
                        _query.setCandidateType(cls, true);


Reply via email to