svn commit: r1153560 [10/15] - in /ofbiz/branches/jackrabbit20100709: ./ applications/accounting/config/ applications/accounting/data/ applications/accounting/entitydef/ applications/accounting/script/org/ofbiz/accounting/invoice/ applications/accounti...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1153560 [10/15] - in /ofbiz/branches/jackrabbit20100709: ./ applications/accounting/config/ applications/accounting/data/ applications/accounting/entitydef/ applications/accounting/script/org/ofbiz/accounting/invoice/ applications/accounti...

sascharodekamp
Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/GenericDelegator.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/GenericDelegator.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/GenericDelegator.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/GenericDelegator.java Wed Aug  3 16:12:58 2011
@@ -27,6 +27,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 
@@ -35,6 +37,7 @@ import javax.xml.parsers.ParserConfigura
 import javolution.util.FastList;
 import javolution.util.FastMap;
 
+import org.ofbiz.base.concurrent.ExecutionPool;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.GeneralRuntimeException;
 import org.ofbiz.base.util.UtilDateTime;
@@ -73,6 +76,7 @@ import org.ofbiz.entity.util.EntityCrypt
 import org.ofbiz.entity.util.EntityFindOptions;
 import org.ofbiz.entity.util.EntityListIterator;
 import org.ofbiz.entity.util.SequenceUtil;
+//import org.ofbiz.service.ServiceDispatcher;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -88,7 +92,6 @@ public class GenericDelegator implements
 
     protected ModelReader modelReader = null;
     protected ModelGroupReader modelGroupReader = null;
-
     /** This flag is only here for lower level technical testing, it shouldn't be user configurable (or at least I don't think so yet); when true all operations without a transaction will be wrapped in one; seems to be necessary for some (all?) XA aware connection pools, and should improve overall stability and consistency */
     public static final boolean alwaysUseTransaction = true;
 
@@ -105,14 +108,15 @@ public class GenericDelegator implements
     protected Map<?,?> andCacheFieldSets = FastMap.newInstance();
 
     protected DistributedCacheClear distributedCacheClear = null;
+    protected boolean enableJMS = true;
     protected EntityEcaHandler<?> entityEcaHandler = null;
     protected SequenceUtil sequencer = null;
     protected EntityCrypto crypto = null;
 
     /** A ThreadLocal variable to allow other methods to specify a user identifier (usually the userLoginId, though technically the Entity Engine doesn't know anything about the UserLogin entity) */
-    protected static ThreadLocal<List<Object>> userIdentifierStack = new ThreadLocal<List<Object>>();
+    protected static ThreadLocal<List<String>> userIdentifierStack = new ThreadLocal<List<String>>();
     /** A ThreadLocal variable to allow other methods to specify a session identifier (usually the visitId, though technically the Entity Engine doesn't know anything about the Visit entity) */
-    protected static ThreadLocal<List<Object>> sessionIdentifierStack = new ThreadLocal<List<Object>>();
+    protected static ThreadLocal<List<String>> sessionIdentifierStack = new ThreadLocal<List<String>>();
 
     private boolean testMode = false;
     private boolean testRollbackInProgress = false;
@@ -129,8 +133,8 @@ public class GenericDelegator implements
         return (GenericDelegator) DelegatorFactory.getDelegator(delegatorName);
     }
 
-    protected static List<Object> getUserIdentifierStack() {
-        List<Object> curValList = userIdentifierStack.get();
+    protected static List<String> getUserIdentifierStack() {
+        List<String> curValList = userIdentifierStack.get();
         if (curValList == null) {
             curValList = FastList.newInstance();
             userIdentifierStack.set(curValList);
@@ -139,39 +143,34 @@ public class GenericDelegator implements
     }
 
     public static String getCurrentUserIdentifier() {
-        List<Object> curValList = getUserIdentifierStack();
-        Object curVal = curValList.size() > 0 ? curValList.get(0) : null;
-        if (curVal == null) {
-            return null;
-        } else {
-            return curVal.toString();
-        }
+        List<String> curValList = getUserIdentifierStack();
+        return curValList.size() > 0 ? curValList.get(0) : null;
     }
 
     public static void pushUserIdentifier(String userIdentifier) {
         if (userIdentifier == null) {
             return;
         }
-        List<Object> curValList = getUserIdentifierStack();
+        List<String> curValList = getUserIdentifierStack();
         curValList.add(0, userIdentifier);
     }
 
     public static String popUserIdentifier() {
-        List<Object> curValList = getUserIdentifierStack();
+        List<String> curValList = getUserIdentifierStack();
         if (curValList.size() == 0) {
             return null;
         } else {
-            return (String) curValList.remove(0);
+            return curValList.remove(0);
         }
     }
 
     public static void clearUserIdentifierStack() {
-        List<Object> curValList = getUserIdentifierStack();
+        List<String> curValList = getUserIdentifierStack();
         curValList.clear();
     }
 
-    protected static List<Object> getSessionIdentifierStack() {
-        List<Object> curValList = sessionIdentifierStack.get();
+    protected static List<String> getSessionIdentifierStack() {
+        List<String> curValList = sessionIdentifierStack.get();
         if (curValList == null) {
             curValList = FastList.newInstance();
             sessionIdentifierStack.set(curValList);
@@ -180,34 +179,29 @@ public class GenericDelegator implements
     }
 
     public static String getCurrentSessionIdentifier() {
-        List<Object> curValList = getSessionIdentifierStack();
-        Object curVal = curValList.size() > 0 ? curValList.get(0) : null;
-        if (curVal == null) {
-            return null;
-        } else {
-            return curVal.toString();
-        }
+        List<String> curValList = getSessionIdentifierStack();
+        return curValList.size() > 0 ? curValList.get(0) : null;
     }
 
     public static void pushSessionIdentifier(String sessionIdentifier) {
         if (sessionIdentifier == null) {
             return;
         }
-        List<Object> curValList = getSessionIdentifierStack();
+        List<String> curValList = getSessionIdentifierStack();
         curValList.add(0, sessionIdentifier);
     }
 
     public static String popSessionIdentifier() {
-        List<Object> curValList = getSessionIdentifierStack();
+        List<String> curValList = getSessionIdentifierStack();
         if (curValList.size() == 0) {
             return null;
         } else {
-            return (String) curValList.remove(0);
+            return curValList.remove(0);
         }
     }
 
     public static void clearSessionIdentifierStack() {
-        List<Object> curValList = getSessionIdentifierStack();
+        List<String> curValList = getSessionIdentifierStack();
         curValList.clear();
     }
 
@@ -218,7 +212,7 @@ public class GenericDelegator implements
     protected GenericDelegator(String delegatorFullName) throws GenericEntityException {
         //if (Debug.infoOn()) Debug.logInfo("Creating new Delegator with name \"" + delegatorFullName + "\".", module);
         this.setDelegatorNames(delegatorFullName);
-        
+
         // before continuing, if there is a tenantId use the base delegator to see if it is valid
         if (UtilValidate.isNotEmpty(this.delegatorTenantId)) {
             Delegator baseDelegator = DelegatorFactory.getDelegator(this.delegatorBaseName);
@@ -229,7 +223,7 @@ public class GenericDelegator implements
                 throw new GenericEntityException("No Tenant record found for delegator [" + this.delegatorFullName + "] with tenantId [" + this.delegatorTenantId + "]");
             }
         }
-        
+
         this.modelReader = ModelReader.getModelReader(delegatorBaseName);
         this.modelGroupReader = ModelGroupReader.getModelGroupReader(delegatorBaseName);
 
@@ -248,29 +242,11 @@ public class GenericDelegator implements
 
         // initialize helpers by group
         Set<String> groupNames = getModelGroupReader().getGroupNames(delegatorBaseName);
+        List<Future<Void>> futures = FastList.newInstance();
         for (String groupName: groupNames) {
-            GenericHelperInfo helperInfo = this.getGroupHelperInfo(groupName);
-            String helperBaseName = helperInfo.getHelperBaseName();
-
-            if (Debug.infoOn()) Debug.logInfo("Delegator \"" + delegatorFullName + "\" initializing helper \"" +
-                    helperBaseName + "\" for entity group \"" + groupName + "\".", module);
-            if (UtilValidate.isNotEmpty(helperInfo.getHelperFullName())) {
-                // pre-load field type defs, the return value is ignored
-                ModelFieldTypeReader.getModelFieldTypeReader(helperBaseName);
-                // get the helper and if configured, do the datasource check
-                GenericHelper helper = GenericHelperFactory.getHelper(helperInfo);
-
-                DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperBaseName);
-                if (datasourceInfo.checkOnStart) {
-                    if (Debug.infoOn()) Debug.logInfo("Doing database check as requested in entityengine.xml with addMissing=" + datasourceInfo.addMissingOnStart, module);
-                    try {
-                        helper.checkDataSource(this.getModelEntityMapByGroup(groupName), null, datasourceInfo.addMissingOnStart);
-                    } catch (GenericEntityException e) {
-                        Debug.logWarning(e, e.getMessage(), module);
-                    }
-                }
-            }
+            futures.add(ExecutionPool.GLOBAL_EXECUTOR.submit(createHelperCallable(groupName)));
         }
+        ExecutionPool.getAllFutures(futures);
 
         // NOTE: doing some things before the ECAs and such to make sure it is in place just in case it is used in a service engine startup thing or something
 
@@ -278,6 +254,42 @@ public class GenericDelegator implements
         this.crypto = new EntityCrypto(this);
     }
 
+    private void initializeOneGenericHelper(String groupName) {
+        GenericHelperInfo helperInfo = this.getGroupHelperInfo(groupName);
+        String helperBaseName = helperInfo.getHelperBaseName();
+
+        if (Debug.infoOn()) {
+            Debug.logInfo("Delegator \"" + delegatorFullName + "\" initializing helper \"" + helperBaseName + "\" for entity group \"" + groupName + "\".", module);
+        }
+        if (UtilValidate.isNotEmpty(helperInfo.getHelperFullName())) {
+            // pre-load field type defs, the return value is ignored
+            ModelFieldTypeReader.getModelFieldTypeReader(helperBaseName);
+            // get the helper and if configured, do the datasource check
+            GenericHelper helper = GenericHelperFactory.getHelper(helperInfo);
+
+            DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperBaseName);
+            if (datasourceInfo.checkOnStart) {
+                if (Debug.infoOn()) {
+                    Debug.logInfo("Doing database check as requested in entityengine.xml with addMissing=" + datasourceInfo.addMissingOnStart, module);
+                }
+                try {
+                    helper.checkDataSource(this.getModelEntityMapByGroup(groupName), null, datasourceInfo.addMissingOnStart);
+                } catch (GenericEntityException e) {
+                    Debug.logWarning(e, e.getMessage(), module);
+                }
+            }
+        }
+    }
+
+    protected Callable<Void> createHelperCallable(final String groupName) {
+        return new Callable<Void>() {
+            public Void call() {
+                initializeOneGenericHelper(groupName);
+                return null;
+            }
+        };
+    }
+
     protected void setDelegatorNames(String delegatorFullName) {
         this.delegatorFullName = delegatorFullName;
 
@@ -308,7 +320,10 @@ public class GenericDelegator implements
             try {
                 Class<?> eecahClass = loader.loadClass(entityEcaHandlerClassName);
                 this.entityEcaHandler = UtilGenerics.cast(eecahClass.newInstance());
+                boolean isJmsEnabled = getEnabledJMS();
+                enableJMS(!getDelegatorInfo().useDistributedCacheClear); // To avoid duplicated JMS listeners (OFBIZ-4296)
                 this.entityEcaHandler.setDelegator(this);
+                enableJMS(isJmsEnabled);
             } catch (ClassNotFoundException e) {
                 Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " was not found, Entity ECA Rules will be disabled", module);
             } catch (InstantiationException e) {
@@ -442,15 +457,19 @@ public class GenericDelegator implements
     }
 
     public GenericHelperInfo getGroupHelperInfo(String entityGroupName) {
-        if (entityGroupName == null) return null;
+        if (entityGroupName == null) {
+            return null;
+        }
         String helperBaseName = this.getGroupHelperName(entityGroupName);
-        if (helperBaseName == null) return null;
+        if (helperBaseName == null) {
+            return null;
+        }
         GenericHelperInfo helperInfo = new GenericHelperInfo(entityGroupName, helperBaseName);
-        
+
         // to avoid infinite recursion, and to behave right for shared org.ofbiz.tenant entities, do nothing with the tenantId if the entityGroupName=org.ofbiz.tenant
         if (UtilValidate.isNotEmpty(this.delegatorTenantId) && !"org.ofbiz.tenant".equals(entityGroupName)) {
             helperInfo.setTenantId(this.delegatorTenantId);
-            
+
             // get the JDBC parameters from the DB for the entityGroupName and tenantId
             try {
                 // NOTE: instead of caching the GenericHelpInfo object do a cached query here and create a new object each time, will avoid issues when the database data changes during run time
@@ -462,21 +481,25 @@ public class GenericDelegator implements
                     helperInfo.setOverrideUsername(tenantDataSource.getString("jdbcUsername"));
                     helperInfo.setOverridePassword(tenantDataSource.getString("jdbcPassword"));
                 } else {
-                    // don't log this, happens too many times: if (Debug.warningOn()) Debug.logWarning("Could not find TenantDataSource information for tenantId=[" + this.delegatorTenantId + "] and entityGroupName=[" + entityGroupName + "] in delegator [" + this.delegatorFullName + "]; will be defaulting to settings for the base delegator name [" + this.delegatorBaseName + "]", module);
+                    /* don't log this, happens too many times:
+                    if (Debug.warningOn()) {
+                        Debug.logWarning("Could not find TenantDataSource information for tenantId=[" + this.delegatorTenantId + "] and entityGroupName=[" + entityGroupName + "] in delegator [" + this.delegatorFullName + "]; will be defaulting to settings for the base delegator name [" + this.delegatorBaseName + "]", module);
+                    }
+                    */
                 }
             } catch (GenericEntityException e) {
                 // don't complain about this too much, just log the error if there is one
                 Debug.logInfo(e, "Error getting TenantDataSource info for tenantId=" + this.delegatorTenantId + ", entityGroupName=" + entityGroupName, module);
             }
-                
+
         }
         return helperInfo;
     }
-    
+
     protected GenericHelperInfo getEntityHelperInfo(String entityName) {
         return this.getGroupHelperInfo(this.getEntityGroupName(entityName));
     }
-    
+
     /* (non-Javadoc)
      * @see org.ofbiz.entity.Delegator#getEntityHelperName(java.lang.String)
      */
@@ -488,8 +511,9 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#getEntityHelperName(org.ofbiz.entity.model.ModelEntity)
      */
     public String getEntityHelperName(ModelEntity entity) {
-        if (entity == null)
+        if (entity == null) {
             return null;
+        }
         return getEntityHelperName(entity.getEntityName());
     }
 
@@ -541,8 +565,9 @@ public class GenericDelegator implements
     public Collection<String> getEntityFieldTypeNames(ModelEntity entity) throws GenericEntityException {
         String helperName = getEntityHelperName(entity);
 
-        if (helperName == null || helperName.length() <= 0)
+        if (helperName == null || helperName.length() <= 0) {
             return null;
+        }
         ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);
 
         if (modelFieldTypeReader == null) {
@@ -1230,9 +1255,9 @@ public class GenericDelegator implements
         value.refreshFromValue(newValue);
     }
 
-   /* (non-Javadoc)
- * @see org.ofbiz.entity.Delegator#storeByCondition(java.lang.String, java.util.Map, org.ofbiz.entity.condition.EntityCondition)
- */
+    /* (non-Javadoc)
+     * @see org.ofbiz.entity.Delegator#storeByCondition(java.lang.String, java.util.Map, org.ofbiz.entity.condition.EntityCondition)
+     */
     public int storeByCondition(String entityName, Map<String, ? extends Object> fieldsToSet, EntityCondition condition) throws GenericEntityException {
         return storeByCondition(entityName, fieldsToSet, condition, true);
     }
@@ -1516,6 +1541,7 @@ public class GenericDelegator implements
     public GenericValue findOne(String entityName, boolean useCache, Object... fields) throws GenericEntityException {
         return findOne(entityName, UtilMisc.toMap(fields), useCache);
     }
+
     /* (non-Javadoc)
      * @see org.ofbiz.entity.Delegator#findOne(java.lang.String, java.util.Map, boolean)
      */
@@ -1690,9 +1716,7 @@ public class GenericDelegator implements
     /* (non-Javadoc)
      * @see org.ofbiz.entity.Delegator#find(java.lang.String, org.ofbiz.entity.condition.EntityCondition, org.ofbiz.entity.condition.EntityCondition, java.util.Set, java.util.List, org.ofbiz.entity.util.EntityFindOptions)
      */
-    public EntityListIterator find(String entityName, EntityCondition whereEntityCondition,
-            EntityCondition havingEntityCondition, Set<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions)
-            throws GenericEntityException {
+    public EntityListIterator find(String entityName, EntityCondition whereEntityCondition, EntityCondition havingEntityCondition, Set<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions) throws GenericEntityException {
 
         // if there is no transaction throw an exception, we don't want to create a transaction here since closing it would mess up the ELI
         if (!TransactionUtil.isTransactionInPlace()) {
@@ -1719,8 +1743,7 @@ public class GenericDelegator implements
 
         ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, dummyValue, false);
         GenericHelper helper = getEntityHelper(modelEntity.getEntityName());
-        EntityListIterator eli = helper.findListIteratorByCondition(modelEntity, whereEntityCondition,
-                havingEntityCondition, fieldsToSelect, orderBy, findOptions);
+        EntityListIterator eli = helper.findListIteratorByCondition(modelEntity, whereEntityCondition, havingEntityCondition, fieldsToSelect, orderBy, findOptions);
         eli.setDelegator(this);
 
         ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, dummyValue, false);
@@ -1730,9 +1753,7 @@ public class GenericDelegator implements
     /* (non-Javadoc)
      * @see org.ofbiz.entity.Delegator#findList(java.lang.String, org.ofbiz.entity.condition.EntityCondition, java.util.Set, java.util.List, org.ofbiz.entity.util.EntityFindOptions, boolean)
      */
-    public List<GenericValue> findList(String entityName, EntityCondition entityCondition,
-            Set<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions, boolean useCache)
-            throws GenericEntityException {
+    public List<GenericValue> findList(String entityName, EntityCondition entityCondition, Set<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions, boolean useCache) throws GenericEntityException {
 
         EntityEcaRuleRunner<?> ecaRunner = null;
         GenericValue dummyValue = null;
@@ -1784,9 +1805,7 @@ public class GenericDelegator implements
     /* (non-Javadoc)
      * @see org.ofbiz.entity.Delegator#findListIteratorByCondition(org.ofbiz.entity.model.DynamicViewEntity, org.ofbiz.entity.condition.EntityCondition, org.ofbiz.entity.condition.EntityCondition, java.util.Collection, java.util.List, org.ofbiz.entity.util.EntityFindOptions)
      */
-    public EntityListIterator findListIteratorByCondition(DynamicViewEntity dynamicViewEntity, EntityCondition whereEntityCondition,
-            EntityCondition havingEntityCondition, Collection<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions)
-            throws GenericEntityException {
+    public EntityListIterator findListIteratorByCondition(DynamicViewEntity dynamicViewEntity, EntityCondition whereEntityCondition, EntityCondition havingEntityCondition, Collection<String> fieldsToSelect, List<String> orderBy, EntityFindOptions findOptions) throws GenericEntityException {
 
         // if there is no transaction throw an exception, we don't want to create a transaction here since closing it would mess up the ELI
         if (!TransactionUtil.isTransactionInPlace()) {
@@ -1910,7 +1929,9 @@ public class GenericDelegator implements
         // put the byAndFields (if not null) into the hash map first,
         // they will be overridden by value's fields if over-specified this is important for security and cleanliness
         Map<String, Object> fields = FastMap.newInstance();
-        if (byAndFields != null) fields.putAll(byAndFields);
+        if (byAndFields != null) {
+            fields.putAll(byAndFields);
+        }
         for (int i = 0; i < relation.getKeyMapsSize(); i++) {
             ModelKeyMap keyMap = relation.getKeyMap(i);
             fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
@@ -1934,7 +1955,9 @@ public class GenericDelegator implements
         // put the byAndFields (if not null) into the hash map first,
         // they will be overridden by value's fields if over-specified this is important for security and cleanliness
         Map<String, Object> fields = FastMap.newInstance();
-        if (byAndFields != null) fields.putAll(byAndFields);
+        if (byAndFields != null) {
+            fields.putAll(byAndFields);
+        }
         for (int i = 0; i < relation.getKeyMapsSize(); i++) {
             ModelKeyMap keyMap = relation.getKeyMap(i);
             fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
@@ -2060,7 +2083,9 @@ public class GenericDelegator implements
             throw new IllegalArgumentException("[GenericDelegator.clearCacheLine] could not find entity for entityName: " + entityName);
         }
         //if never cached, then don't bother clearing
-        if (entity.getNeverCache()) return;
+        if (entity.getNeverCache()) {
+            return;
+        }
 
         GenericValue dummyValue = GenericValue.create(this, entity, fields);
         this.clearCacheLineFlexible(dummyValue);
@@ -2102,7 +2127,9 @@ public class GenericDelegator implements
     public void clearCacheLineByCondition(String entityName, EntityCondition condition, boolean distribute) {
         if (entityName != null) {
             //if never cached, then don't bother clearing
-            if (getModelEntity(entityName).getNeverCache()) return;
+            if (getModelEntity(entityName).getNeverCache()) {
+                return;
+            }
 
             cache.remove(entityName, condition);
 
@@ -2123,10 +2150,14 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#clearCacheLine(org.ofbiz.entity.GenericPK, boolean)
      */
     public void clearCacheLine(GenericPK primaryKey, boolean distribute) {
-        if (primaryKey == null) return;
+        if (primaryKey == null) {
+            return;
+        }
 
         //if never cached, then don't bother clearing
-        if (primaryKey.getModelEntity().getNeverCache()) return;
+        if (primaryKey.getModelEntity().getNeverCache()) {
+            return;
+        }
 
         cache.remove(primaryKey);
 
@@ -2152,10 +2183,14 @@ public class GenericDelegator implements
         // on remove don't clear by and for new values, but do for original values
 
         // Debug.logInfo("running clearCacheLine for value: " + value + ", distribute: " + distribute, module);
-        if (value == null) return;
+        if (value == null) {
+            return;
+        }
 
         //if never cached, then don't bother clearing
-        if (value.getModelEntity().getNeverCache()) return;
+        if (value.getModelEntity().getNeverCache()) {
+            return;
+        }
 
         cache.remove(value);
 
@@ -2168,7 +2203,9 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#clearAllCacheLinesByDummyPK(java.util.Collection)
      */
     public void clearAllCacheLinesByDummyPK(Collection<GenericPK> dummyPKs) {
-        if (dummyPKs == null) return;
+        if (dummyPKs == null) {
+            return;
+        }
         for (GenericEntity entity: dummyPKs) {
             this.clearCacheLineFlexible(entity);
         }
@@ -2178,7 +2215,9 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#clearAllCacheLinesByValue(java.util.Collection)
      */
     public void clearAllCacheLinesByValue(Collection<GenericValue> values) {
-        if (values == null) return;
+        if (values == null) {
+            return;
+        }
         for (GenericValue value: values) {
             this.clearCacheLine(value);
         }
@@ -2188,7 +2227,9 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#getFromPrimaryKeyCache(org.ofbiz.entity.GenericPK)
      */
     public GenericValue getFromPrimaryKeyCache(GenericPK primaryKey) {
-        if (primaryKey == null) return null;
+        if (primaryKey == null) {
+            return null;
+        }
         GenericValue value = cache.get(primaryKey);
         if (value == GenericValue.NULL_VALUE) {
             return null;
@@ -2200,7 +2241,9 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#putInPrimaryKeyCache(org.ofbiz.entity.GenericPK, org.ofbiz.entity.GenericValue)
      */
     public void putInPrimaryKeyCache(GenericPK primaryKey, GenericValue value) {
-        if (primaryKey == null) return;
+        if (primaryKey == null) {
+            return;
+        }
 
         if (primaryKey.getModelEntity().getNeverCache()) {
             Debug.logWarning("Tried to put a value of the " + value.getEntityName() + " entity in the BY PRIMARY KEY cache but this entity has never-cache set to true, not caching.", module);
@@ -2216,7 +2259,9 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#putAllInPrimaryKeyCache(java.util.List)
      */
     public void putAllInPrimaryKeyCache(List<GenericValue> values) {
-        if (values == null) return;
+        if (values == null) {
+            return;
+        }
         for (GenericValue value: values) {
             this.putInPrimaryKeyCache(value.getPrimaryKey(), value);
         }
@@ -2234,7 +2279,9 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#readXmlDocument(java.net.URL)
      */
     public List<GenericValue> readXmlDocument(URL url) throws SAXException, ParserConfigurationException, java.io.IOException {
-        if (url == null) return null;
+        if (url == null) {
+            return null;
+        }
         return this.makeValues(UtilXml.readXmlDocument(url, false));
     }
 
@@ -2242,13 +2289,16 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#makeValues(org.w3c.dom.Document)
      */
     public List<GenericValue> makeValues(Document document) {
-        if (document == null) return null;
+        if (document == null) {
+            return null;
+        }
         List<GenericValue> values = FastList.newInstance();
 
         Element docElement = document.getDocumentElement();
 
-        if (docElement == null)
+        if (docElement == null) {
             return null;
+        }
         if (!"entity-engine-xml".equals(docElement.getTagName())) {
             Debug.logError("[GenericDelegator.makeValues] Root node was not <entity-engine-xml>", module);
             throw new java.lang.IllegalArgumentException("Root node was not <entity-engine-xml>");
@@ -2262,8 +2312,9 @@ public class GenericDelegator implements
                     Element element = (Element) curChild;
                     GenericValue value = this.makeValue(element);
 
-                    if (value != null)
+                    if (value != null) {
                         values.add(value);
+                    }
                 }
             } while ((curChild = curChild.getNextSibling()) != null);
         } else {
@@ -2286,14 +2337,18 @@ public class GenericDelegator implements
      * @see org.ofbiz.entity.Delegator#makeValue(org.w3c.dom.Element)
      */
     public GenericValue makeValue(Element element) {
-        if (element == null) return null;
+        if (element == null) {
+            return null;
+        }
         String entityName = element.getTagName();
 
         // if a dash or colon is in the tag name, grab what is after it
-        if (entityName.indexOf('-') > 0)
+        if (entityName.indexOf('-') > 0) {
             entityName = entityName.substring(entityName.indexOf('-') + 1);
-        if (entityName.indexOf(':') > 0)
+        }
+        if (entityName.indexOf(':') > 0) {
             entityName = entityName.substring(entityName.indexOf(':') + 1);
+        }
         GenericValue value = this.makeValue(entityName);
 
         ModelEntity modelEntity = value.getModelEntity();
@@ -2332,14 +2387,20 @@ public class GenericDelegator implements
         }
 
         protected void evalRules(String event, String currentOperation, GenericEntity value, boolean isError) throws GenericEntityException {
-            if (entityEcaHandler == null) return;
-            //if (!"find".equals(currentOperation)) Debug.logWarning("evalRules for entity " + value.getEntityName() + ", currentOperation " + currentOperation + ", event " + event, module);
+            if (entityEcaHandler == null) {
+                return;
+            }
+            //if (!"find".equals(currentOperation)) {
+            //    Debug.logWarning("evalRules for entity " + value.getEntityName() + ", currentOperation " + currentOperation + ", event " + event, module);
+            //}
             entityEcaHandler.evalRules(currentOperation, eventMap, event, value, isError);
         }
     }
 
     protected EntityEcaRuleRunner<?> getEcaRuleRunner(String entityName) {
-        if (this.testRollbackInProgress) return createEntityEcaRuleRunner(null, null);
+        if (this.testRollbackInProgress) {
+            return createEntityEcaRuleRunner(null, null);
+        }
         return createEntityEcaRuleRunner(this.entityEcaHandler, entityName);
     }
 
@@ -2407,7 +2468,7 @@ public class GenericDelegator implements
                 synchronized (this) {
                     if (sequencer == null) {
                         ModelEntity seqEntity = this.getModelEntity("SequenceValueItem");
-                        sequencer = new SequenceUtil(this.getEntityHelperInfo("SequenceValueItem"), seqEntity, "seqName", "seqId");
+                        sequencer = new SequenceUtil(this, this.getEntityHelperInfo("SequenceValueItem"), seqEntity, "seqName", "seqId");
                     }
                 }
             }
@@ -2610,7 +2671,9 @@ public class GenericDelegator implements
     }
 
     protected void absorbList(List<GenericValue> lst) {
-        if (lst == null) return;
+        if (lst == null) {
+            return;
+        }
         for (GenericValue value: lst) {
             value.setDelegator(this);
         }
@@ -2671,14 +2734,14 @@ public class GenericDelegator implements
                 }
             }
         }
-        
-        if (!(newValueText==null ? "" : newValueText).equals((oldValueText==null ? "" : oldValueText))) {
+
+        if (!(newValueText == null ? "" : newValueText).equals((oldValueText == null ? "" : oldValueText))) {
             // only save changed values
             GenericValue entityAuditLog = this.makeValue("EntityAuditLog");
             entityAuditLog.set("auditHistorySeqId", this.getNextSeqId("EntityAuditLog"));
             entityAuditLog.set("changedEntityName", value.getEntityName());
             entityAuditLog.set("changedFieldName", mf.getName());
-            
+
             String pkCombinedValueText = value.getPkShortValueString();
             if (pkCombinedValueText.length() > 250) {
                 // uh-oh, the string is too long!
@@ -2690,7 +2753,7 @@ public class GenericDelegator implements
             entityAuditLog.set("changedDate", nowTimestamp);
             entityAuditLog.set("changedByInfo", getCurrentUserIdentifier());
             entityAuditLog.set("changedSessionInfo", getCurrentSessionIdentifier());
-            this.create(entityAuditLog);      
+            this.create(entityAuditLog);
         }
     }
 
@@ -2770,7 +2833,9 @@ public class GenericDelegator implements
         Debug.logInfo("Rolling back " + testOperations.size() + " entity operations", module);
         while (!this.testOperations.isEmpty()) {
             TestOperation testOperation = this.testOperations.pollLast();
-            if (testOperation == null) break;
+            if (testOperation == null) {
+                break;
+            }
             try {
                 if (testOperation.getOperation().equals(OperationType.INSERT)) {
                     this.removeValue(testOperation.getValue());
@@ -2788,19 +2853,22 @@ public class GenericDelegator implements
         this.testMode = true;
     }
 
-    public class TestOperation {
+    public final class TestOperation {
         private final OperationType operation;
+        private final GenericValue value;
+
+        public TestOperation(OperationType operation, GenericValue value) {
+            this.operation = operation;
+            this.value = value;
+        }
+
         public OperationType getOperation() {
             return operation;
         }
+
         public GenericValue getValue() {
             return value;
         }
-        private final GenericValue value;
-        public TestOperation(OperationType operation, GenericValue value) {
-            this.operation = operation;
-            this.value = value;
-        }
     }
 
     /* (non-Javadoc)
@@ -2836,4 +2904,26 @@ public class GenericDelegator implements
             Debug.logVerbose("Distributed Cache Clear System disabled for delegator [" + delegatorFullName + "]", module);
         }
     }
+
+    /* (non-Javadoc)
+     * @see org.ofbiz.entity.Delegator#enableJMS()
+     */
+    public void enableJMS(boolean enable) {
+        this.enableJMS = enable;
+    }
+
+    /* (non-Javadoc)
+     * @see org.ofbiz.entity.Delegator#getEnableJMS()
+     */
+    public boolean getEnabledJMS() {
+        return this.enableJMS;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.ofbiz.entity.Delegator#getEnableJMS()
+     */
+    public boolean useDistributedCacheClear() {
+        return this.getDelegatorInfo().useDistributedCacheClear;
+    }
+    
 }

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityConditionSubSelect.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityConditionSubSelect.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityConditionSubSelect.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityConditionSubSelect.java Wed Aug  3 16:12:58 2011
@@ -76,7 +76,7 @@ public class EntityConditionSubSelect ex
             sql.append(localModelField.getColName());
 
             // FROM clause and when necessary the JOIN or LEFT JOIN clause(s) as well
-            sql.append(SqlJdbcUtil.makeFromClause(localModelEntity, datasourceInfo));
+            sql.append(SqlJdbcUtil.makeFromClause(localModelEntity, null, datasourceInfo));
 
             // WHERE clause
             StringBuilder whereString = new StringBuilder();

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityExpr.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityExpr.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityExpr.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityExpr.java Wed Aug  3 16:12:58 2011
@@ -219,15 +219,16 @@ public class EntityExpr extends EntityCo
         }
 
         String fieldName = null;
+        ModelField curField;
         if (this.lhs instanceof EntityFieldValue) {
             EntityFieldValue efv = (EntityFieldValue) this.lhs;
             fieldName = efv.getFieldName();
+            curField = efv.getModelField(modelEntity);
         } else {
             // nothing to check
             return;
         }
 
-        ModelField curField = modelEntity.getField(fieldName);
         if (curField == null) {
             throw new IllegalArgumentException("FieldName " + fieldName + " not found for entity: " + modelEntity.getEntityName());
         }
@@ -263,7 +264,7 @@ public class EntityExpr extends EntityCo
         } else if (value instanceof EntityFieldValue) {
             EntityFieldValue efv = (EntityFieldValue) this.lhs;
             String rhsFieldName = efv.getFieldName();
-            ModelField rhsField = modelEntity.getField(fieldName);
+            ModelField rhsField = efv.getModelField(modelEntity);
             if (rhsField == null) {
                 throw new IllegalArgumentException("FieldName " + rhsFieldName + " not found for entity: " + modelEntity.getEntityName());
             }

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityFieldValue.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityFieldValue.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityFieldValue.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/EntityFieldValue.java Wed Aug  3 16:12:58 2011
@@ -123,6 +123,14 @@ public class EntityFieldValue extends En
 
     @Override
     public ModelField getModelField(ModelEntity modelEntity) {
+        if (this.modelViewEntity != null) {
+            if (this.entityAlias != null) {
+                ModelEntity memberModelEntity = modelViewEntity.getMemberModelEntity(entityAlias);
+                return getField(memberModelEntity, fieldName);
+            } else {
+                return getField(modelViewEntity, fieldName);
+            }
+        }
         return getField(modelEntity, fieldName);
     }
 

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/OrderByList.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/OrderByList.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/OrderByList.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/condition/OrderByList.java Wed Aug  3 16:12:58 2011
@@ -98,6 +98,7 @@ public class OrderByList implements Comp
         int result = 0;
         for (OrderByItem orderByItem: orderByList) {
             result = orderByItem.compare(entity1, entity2);
+            if (result != 0) break;
         }
         return result;
     }

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/config/DatasourceInfo.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/config/DatasourceInfo.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/config/DatasourceInfo.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/config/DatasourceInfo.java Wed Aug  3 16:12:58 2011
@@ -76,6 +76,7 @@ public class DatasourceInfo {
     public String tableType = null;
     public String characterSet = null;
     public String collate = null;
+    public int maxWorkerPoolSize = 1;
 
     public DatasourceInfo(Element element) {
         this.name = element.getAttribute("name");
@@ -110,6 +111,7 @@ public class DatasourceInfo {
             Debug.logWarning("datasource def not found with name " + this.name + ", using default for table-type (none)", module);
             Debug.logWarning("datasource def not found with name " + this.name + ", using default for character-set (none)", module);
             Debug.logWarning("datasource def not found with name " + this.name + ", using default for collate (none)", module);
+            Debug.logWarning("datasource def not found with name " + this.name + ", using default for max-worker-pool-size (1)", module);
         } else {
             this.schemaName = datasourceElement.getAttribute("schema-name");
             // anything but false is true
@@ -161,6 +163,16 @@ public class DatasourceInfo {
             this.tableType = datasourceElement.getAttribute("table-type");
             this.characterSet = datasourceElement.getAttribute("character-set");
             this.collate = datasourceElement.getAttribute("collate");
+            try {
+                this.maxWorkerPoolSize = Integer.parseInt(datasourceElement.getAttribute("max-worker-pool-size"));
+                if (this.maxWorkerPoolSize == 0) {
+                    this.maxWorkerPoolSize = 1;
+                } else if (this.maxWorkerPoolSize < -2) {
+                    this.maxWorkerPoolSize = -1;
+                }
+            } catch (Exception e) {
+                Debug.logWarning("Could not parse result-fetch-size value for datasource with name " + this.name + ", using JDBC driver default value", module);
+            }
         }
         if (UtilValidate.isEmpty(this.fkStyle)) this.fkStyle = "name_constraint";
         if (UtilValidate.isEmpty(this.joinStyle)) this.joinStyle = "ansi";

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java Wed Aug  3 16:12:58 2011
@@ -29,11 +29,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.ExecutorService;
 
 import javolution.util.FastList;
 import javolution.util.FastMap;
 import javolution.util.FastSet;
 
+import org.ofbiz.base.concurrent.ExecutionPool;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.Delegator;
@@ -72,9 +76,11 @@ public class GenericDAO {
     public static final String module = GenericDAO.class.getName();
 
     private static final FastMap<String, GenericDAO> genericDAOs = FastMap.newInstance();
+    private static final ThreadGroup GENERIC_DAO_THREAD_GROUP = new ThreadGroup("GenericDAO");
     private final GenericHelperInfo helperInfo;
     private final ModelFieldTypeReader modelFieldTypeReader;
     private final DatasourceInfo datasourceInfo;
+    private final ExecutorService executor;
 
     public static GenericDAO getGenericDAO(GenericHelperInfo helperInfo) {
         GenericDAO newGenericDAO = genericDAOs.get(helperInfo.getHelperFullName());
@@ -90,6 +96,11 @@ public class GenericDAO {
         this.helperInfo = helperInfo;
         this.modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperInfo.getHelperBaseName());
         this.datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperInfo.getHelperBaseName());
+        this.executor = ExecutionPool.getExecutor(GENERIC_DAO_THREAD_GROUP, "entity-datasource(" + helperInfo.getHelperFullName() + ")", datasourceInfo.maxWorkerPoolSize, false);
+    }
+
+    public <T> Future<T> submitWork(Callable<T> callable) throws GenericEntityException {
+        return this.executor.submit(callable);
     }
 
     private void addFieldIfMissing(List<ModelField> fieldsToSave, String fieldName, ModelEntity modelEntity) {
@@ -514,7 +525,7 @@ public class GenericDAO {
             sqlBuffer.append("*");
         }
 
-        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, datasourceInfo));
+        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, modelFieldTypeReader, datasourceInfo));
         sqlBuffer.append(SqlJdbcUtil.makeWhereClause(modelEntity, modelEntity.getPkFieldsUnmodifiable(), entity, "AND", datasourceInfo.joinStyle));
 
         try {
@@ -583,7 +594,7 @@ public class GenericDAO {
         } else {
             sqlBuffer.append("*");
         }
-        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, datasourceInfo));
+        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, modelFieldTypeReader, datasourceInfo));
         sqlBuffer.append(SqlJdbcUtil.makeWhereClause(modelEntity, modelEntity.getPkFieldsUnmodifiable(), entity, "AND", datasourceInfo.joinStyle));
 
         SQLProcessor sqlP = new SQLProcessor(helperInfo);
@@ -649,12 +660,16 @@ public class GenericDAO {
         if (UtilValidate.isNotEmpty(fieldsToSelect)) {
             Set<String> tempKeys = FastSet.newInstance();
             tempKeys.addAll(fieldsToSelect);
+            Set<String> fieldSetsToInclude = FastSet.newInstance();
+            Set<String> addedFields = FastSet.newInstance();
             for (String fieldToSelect : fieldsToSelect) {
                 if (tempKeys.contains(fieldToSelect)) {
                     ModelField curField = modelEntity.getField(fieldToSelect);
                     if (curField != null) {
+                        fieldSetsToInclude.add(curField.getFieldSet());
                         selectFields.add(curField);
                         tempKeys.remove(fieldToSelect);
+                        addedFields.add(fieldToSelect);
                     }
                 }
             }
@@ -662,6 +677,37 @@ public class GenericDAO {
             if (tempKeys.size() > 0) {
                 throw new GenericModelException("In selectListIteratorByCondition invalid field names specified: " + tempKeys.toString());
             }
+            fieldSetsToInclude.remove("");
+            if (verboseOn) {
+                Debug.logInfo("[" + modelEntity.getEntityName() + "]: field-sets to include: " + fieldSetsToInclude, module);
+            }
+            if (UtilValidate.isNotEmpty(fieldSetsToInclude)) {
+                Iterator<ModelField> fieldIter = modelEntity.getFieldsIterator();
+                Set<String> extraFields = FastSet.newInstance();
+                Set<String> reasonSets = FastSet.newInstance();
+                while (fieldIter.hasNext()) {
+                    ModelField curField = fieldIter.next();
+                    String fieldSet = curField.getFieldSet();
+                    if (UtilValidate.isEmpty(fieldSet)) {
+                        continue;
+                    }
+                    if (!fieldSetsToInclude.contains(fieldSet)) {
+                        continue;
+                    }
+                    String fieldName = curField.getName();
+                    if (addedFields.contains(fieldName)) {
+                        continue;
+                    }
+                    reasonSets.add(fieldSet);
+                    extraFields.add(fieldName);
+                    addedFields.add(fieldName);
+                    selectFields.add(curField);
+                }
+                if (verboseOn) {
+                    Debug.logInfo("[" + modelEntity.getEntityName() + "]: auto-added select fields: " + extraFields, module);
+                    Debug.logInfo("[" + modelEntity.getEntityName() + "]: auto-added field-sets: " + reasonSets, module);
+                }
+            }
         } else {
             selectFields = modelEntity.getFieldsUnmodifiable();
         }
@@ -690,7 +736,7 @@ public class GenericDAO {
         }
 
         // FROM clause and when necessary the JOIN or LEFT JOIN clause(s) as well
-        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, datasourceInfo));
+        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, modelFieldTypeReader, datasourceInfo));
 
         // WHERE clause
         List<EntityConditionParam> whereEntityConditionParams = FastList.newInstance();
@@ -1024,7 +1070,7 @@ public class GenericDAO {
         }
 
         // FROM clause and when necessary the JOIN or LEFT JOIN clause(s) as well
-        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, datasourceInfo));
+        sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, modelFieldTypeReader, datasourceInfo));
 
         // WHERE clause
         List<EntityConditionParam> whereEntityConditionParams = FastList.newInstance();
@@ -1164,13 +1210,13 @@ public class GenericDAO {
     /* ====================================================================== */
 
     public void checkDb(Map<String, ModelEntity> modelEntities, List<String> messages, boolean addMissing) {
-        DatabaseUtil dbUtil = new DatabaseUtil(this.helperInfo);
+        DatabaseUtil dbUtil = new DatabaseUtil(this.helperInfo, this.executor);
         dbUtil.checkDb(modelEntities, messages, addMissing);
     }
 
     /** Creates a list of ModelEntity objects based on meta data from the database */
     public List<ModelEntity> induceModelFromDb(Collection<String> messages) {
-        DatabaseUtil dbUtil = new DatabaseUtil(this.helperInfo);
+        DatabaseUtil dbUtil = new DatabaseUtil(this.helperInfo, this.executor);
         return dbUtil.induceModelFromDb(messages);
     }
 }

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java Wed Aug  3 16:12:58 2011
@@ -24,6 +24,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
 
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericPK;
@@ -46,6 +48,8 @@ public interface GenericHelper {
      */
     public String getHelperName();
 
+    public <T> Future<T> submitWork(Callable<T> callable) throws GenericEntityException;
+
     /** Creates a Entity in the form of a GenericValue and write it to the database
      *@return GenericValue instance containing the new instance
      */

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java Wed Aug  3 16:12:58 2011
@@ -23,6 +23,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
 
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.entity.GenericEntityException;
@@ -54,6 +56,10 @@ public class GenericHelperDAO implements
         return this.helperInfo.getHelperFullName();
     }
 
+    public <T> Future<T> submitWork(Callable<T> callable) throws GenericEntityException {
+        return genericDAO.submitWork(callable);
+    }
+
     /** Creates a Entity in the form of a GenericValue and write it to the database
      *@return GenericValue instance containing the new instance
      */

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/MemoryHelper.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/MemoryHelper.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/MemoryHelper.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/datasource/MemoryHelper.java Wed Aug  3 16:12:58 2011
@@ -27,12 +27,18 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.ExecutorService;
 
+import org.ofbiz.base.concurrent.ExecutionPool;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericNotImplementedException;
 import org.ofbiz.entity.GenericPK;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.config.DatasourceInfo;
+import org.ofbiz.entity.config.EntityConfigUtil;
 import org.ofbiz.entity.condition.EntityCondition;
 import org.ofbiz.entity.jdbc.SqlJdbcUtil;
 import org.ofbiz.entity.model.ModelEntity;
@@ -52,12 +58,14 @@ public class MemoryHelper implements Gen
 
     public static final String module = MemoryHelper.class.getName();
     private static Map<String, HashMap<GenericPK, GenericValue>> cache = new HashMap<String, HashMap<GenericPK, GenericValue>>();
+    private static final ThreadGroup MEMORY_HELPER_THREAD_GROUP = new ThreadGroup("MemoryHelper");
 
     public static void clearCache() {
         cache = new HashMap<String, HashMap<GenericPK, GenericValue>>();
     }
 
     private String helperName;
+    protected ExecutorService executor;
 
     private boolean addToCache(GenericValue value) {
         if (value == null) {
@@ -272,12 +280,18 @@ public class MemoryHelper implements Gen
     public MemoryHelper(String helperName) {
         this.helperName = helperName;
         modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);
+        DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperName);
+        this.executor = ExecutionPool.getExecutor(MEMORY_HELPER_THREAD_GROUP, "entity-datasource(" + helperName + ")", datasourceInfo.maxWorkerPoolSize, false);
     }
 
     public String getHelperName() {
         return helperName;
     }
 
+    public <T> Future<T> submitWork(Callable<T> callable) throws GenericEntityException {
+        return this.executor.submit(callable);
+    }
+
     public GenericValue create(GenericValue value) throws GenericEntityException {
         if (addToCache(value)) {
             return value;

Modified: ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/jdbc/DatabaseUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/jdbc/DatabaseUtil.java?rev=1153560&r1=1153559&r2=1153560&view=diff
==============================================================================
--- ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/jdbc/DatabaseUtil.java (original)
+++ ofbiz/branches/jackrabbit20100709/framework/entity/src/org/ofbiz/entity/jdbc/DatabaseUtil.java Wed Aug  3 16:12:58 2011
@@ -19,6 +19,7 @@
 package org.ofbiz.entity.jdbc;
 
 import java.io.Serializable;
+import java.lang.reflect.Method;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
@@ -32,12 +33,17 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
 
 import javolution.util.FastList;
 import javolution.util.FastMap;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import org.ofbiz.base.concurrent.ExecutionPool;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilTimer;
 import org.ofbiz.base.util.UtilValidate;
@@ -76,12 +82,18 @@ public class DatabaseUtil {
     protected String password = null;
 
     boolean isLegacy = false;
+    protected ExecutorService executor;
 
     // OFBiz DatabaseUtil
     public DatabaseUtil(GenericHelperInfo helperInfo) {
+        this(helperInfo, null);
+    }
+
+    public DatabaseUtil(GenericHelperInfo helperInfo, ExecutorService executor) {
         this.helperInfo = helperInfo;
         this.modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperInfo.getHelperBaseName());
         this.datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperInfo.getHelperBaseName());
+        this.executor = executor;
     }
 
     // Legacy DatabaseUtil
@@ -93,6 +105,31 @@ public class DatabaseUtil {
         this.isLegacy = true;
     }
 
+    protected <T> Future<T> submitWork(Callable<T> callable) {
+        if (this.executor == null) {
+            FutureTask<T> task = new FutureTask<T>(callable);
+            task.run();
+            return task;
+        }
+        return this.executor.submit(callable);
+    }
+
+    protected <T> List<Future<T>> submitAll(Collection<? extends Callable<T>> tasks) {
+        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+        if (this.executor == null) {
+            for (Callable<T> callable: tasks) {
+                FutureTask<T> task = new FutureTask<T>(callable);
+                task.run();
+                futures.add(task);
+            }
+            return futures;
+        }
+        for (Callable<T> callable: tasks) {
+            futures.add(this.executor.submit(callable));
+        }
+        return futures;
+    }
+
     protected Connection getConnection() throws SQLException, GenericEntityException {
         Connection connection = null;
         if (!isLegacy) {
@@ -197,6 +234,7 @@ public class DatabaseUtil {
             Debug.logError(message, module);
             return;
         }
+        List<Future<CreateTableCallable>> tableFutures = FastList.newInstance();
         for (ModelEntity entity: modelEntityList) {
             curEnt++;
 
@@ -385,20 +423,13 @@ public class DatabaseUtil {
 
                 if (addMissing) {
                     // create the table
-                    String errMsg = createTable(entity, modelEntities, false);
-                    if (UtilValidate.isNotEmpty(errMsg)) {
-                        message = "Could not create table [" + tableName + "]: " + errMsg;
-                        Debug.logError(message, module);
-                        if (messages != null) messages.add(message);
-                    } else {
-                        entitiesAdded.add(entity);
-                        message = "Created table [" + tableName + "]";
-                        Debug.logImportant(message, module);
-                        if (messages != null) messages.add(message);
-                    }
+                    tableFutures.add(submitWork(new CreateTableCallable(entity, modelEntities, tableName)));
                 }
             }
         }
+        for (CreateTableCallable tableCallable: ExecutionPool.getAllFutures(tableFutures)) {
+            tableCallable.updateData(messages, entitiesAdded);
+        }
 
         timer.timerString("After Individual Table/Column Check");
 
@@ -412,11 +443,20 @@ public class DatabaseUtil {
         // for each newly added table, add fk indices
         if (datasourceInfo.useFkIndices) {
             int totalFkIndices = 0;
+            List<Future<AbstractCountingCallable>> fkIndicesFutures = FastList.newInstance();
             for (ModelEntity curEntity: entitiesAdded) {
                 if (curEntity.getRelationsOneSize() > 0) {
-                    totalFkIndices += this.createForeignKeyIndices(curEntity, datasourceInfo.constraintNameClipLength, messages);
+                    fkIndicesFutures.add(submitWork(new AbstractCountingCallable(curEntity, modelEntities) {
+                        public AbstractCountingCallable call() throws Exception {
+                            count = createForeignKeyIndices(entity, datasourceInfo.constraintNameClipLength, messages);
+                            return this;
+                        }
+                    }));
                 }
             }
+            for (AbstractCountingCallable fkIndicesCallable: ExecutionPool.getAllFutures(fkIndicesFutures)) {
+                totalFkIndices += fkIndicesCallable.updateData(messages);
+            }
             if (totalFkIndices > 0) Debug.logImportant("==== TOTAL Foreign Key Indices Created: " + totalFkIndices, module);
         }
 
@@ -432,11 +472,21 @@ public class DatabaseUtil {
         // for each newly added table, add declared indexes
         if (datasourceInfo.useIndices) {
             int totalDis = 0;
+            List<Future<AbstractCountingCallable>> disFutures = FastList.newInstance();
             for (ModelEntity curEntity: entitiesAdded) {
                 if (curEntity.getIndexesSize() > 0) {
-                    totalDis += this.createDeclaredIndices(curEntity, messages);
+                    disFutures.add(submitWork(new AbstractCountingCallable(curEntity,  modelEntities) {
+                    public AbstractCountingCallable call() throws Exception {
+                        count = createDeclaredIndices(entity, messages);
+                        return this;
+                    }
+                }));
+
                 }
             }
+            for (AbstractCountingCallable disCallable: ExecutionPool.getAllFutures(disFutures)) {
+                totalDis += disCallable.updateData(messages);
+            }
             if (totalDis > 0) Debug.logImportant("==== TOTAL Declared Indices Created: " + totalDis, module);
         }
 
@@ -798,6 +848,80 @@ public class DatabaseUtil {
         return dbData;
     }
 
+    private static final List<Detection> detections = new ArrayList<Detection>();
+    private static final String goodFormatStr;
+    private static final String badFormatStr;
+
+    private static class Detection {
+        protected final String name;
+        protected final boolean required;
+        protected final Method method;
+        protected final Object[] params;
+
+        protected Detection(String name, boolean required, String methodName, Object... params) throws NoSuchMethodException {
+            this.name = name;
+            this.required = required;
+            Class[] paramTypes = new Class[params.length];
+            for (int i = 0; i < params.length; i++) {
+                Class<?> paramType = params[i].getClass();
+                if (paramType == Integer.class) {
+                    paramType = Integer.TYPE;
+                }
+                paramTypes[i] = paramType;
+            }
+            method = DatabaseMetaData.class.getMethod(methodName, paramTypes);
+            this.params = params;
+        }
+    }
+
+    static {
+        try {
+            detections.add(new Detection("supports transactions", true, "supportsTransactions"));
+            detections.add(new Detection("isolation None", false, "supportsTransactionIsolationLevel", Connection.TRANSACTION_NONE));
+            detections.add(new Detection("isolation ReadCommitted", false, "supportsTransactionIsolationLevel", Connection.TRANSACTION_READ_COMMITTED));
+            detections.add(new Detection("isolation ReadUncommitted", false, "supportsTransactionIsolationLevel", Connection.TRANSACTION_READ_UNCOMMITTED));
+            detections.add(new Detection("isolation RepeatableRead", false, "supportsTransactionIsolationLevel", Connection.TRANSACTION_REPEATABLE_READ));
+            detections.add(new Detection("isolation Serializable", false, "supportsTransactionIsolationLevel", Connection.TRANSACTION_SERIALIZABLE));
+            detections.add(new Detection("forward only type", false, "supportsResultSetType", ResultSet.TYPE_FORWARD_ONLY));
+            detections.add(new Detection("scroll sensitive type", false, "supportsResultSetType", ResultSet.TYPE_SCROLL_SENSITIVE));
+            detections.add(new Detection("scroll insensitive type", false, "supportsResultSetType", ResultSet.TYPE_SCROLL_INSENSITIVE));
+            detections.add(new Detection("is case sensitive", false, "supportsMixedCaseIdentifiers"));
+            detections.add(new Detection("stores LowerCase", false, "storesLowerCaseIdentifiers"));
+            detections.add(new Detection("stores MixedCase", false, "storesMixedCaseIdentifiers"));
+            detections.add(new Detection("stores UpperCase", false, "storesUpperCaseIdentifiers"));
+            detections.add(new Detection("max table name length", false, "getMaxTableNameLength"));
+            detections.add(new Detection("max column name length", false, "getMaxColumnNameLength"));
+            detections.add(new Detection("concurrent connections", false, "getMaxConnections"));
+            detections.add(new Detection("concurrent statements", false, "getMaxStatements"));
+            detections.add(new Detection("ANSI SQL92 Entry", false, "supportsANSI92EntryLevelSQL"));
+            detections.add(new Detection("ANSI SQL92 Intermediate", false, "supportsANSI92IntermediateSQL"));
+            detections.add(new Detection("ANSI SQL92 Full", false, "supportsANSI92FullSQL"));
+            detections.add(new Detection("ODBC SQL Grammar Core", false, "supportsCoreSQLGrammar"));
+            detections.add(new Detection("ODBC SQL Grammar Extended", false, "supportsExtendedSQLGrammar"));
+            detections.add(new Detection("ODBC SQL Grammar Minimum", false, "supportsMinimumSQLGrammar"));
+            detections.add(new Detection("outer joins", true, "supportsOuterJoins"));
+            detections.add(new Detection("limited outer joins", false, "supportsLimitedOuterJoins"));
+            detections.add(new Detection("full outer joins", false, "supportsFullOuterJoins"));
+            detections.add(new Detection("group by", true, "supportsGroupBy"));
+            detections.add(new Detection("group by not in select", false, "supportsGroupByUnrelated"));
+            detections.add(new Detection("column aliasing", false, "supportsColumnAliasing"));
+            detections.add(new Detection("order by not in select", false, "supportsOrderByUnrelated"));
+            detections.add(new Detection("alter table add column", true, "supportsAlterTableWithAddColumn"));
+            detections.add(new Detection("non-nullable column", true, "supportsNonNullableColumns"));
+            //detections.add(new Detection("", false, "", ));
+        } catch (NoSuchMethodException e) {
+            throw (InternalError) new InternalError(e.getMessage()).initCause(e);
+        }
+        int maxWidth = 0;
+        for (Detection detection: detections) {
+            if (detection.name.length() > maxWidth) {
+                maxWidth = detection.name.length();
+            }
+        }
+        goodFormatStr = "- %-" + maxWidth + "s [%s]%s";
+        badFormatStr = "- %-" + maxWidth + "s [ DETECTION FAILED ]%s";
+    }
+
     public void printDbMiscData(DatabaseMetaData dbData, Connection con) {
         if (dbData == null) {
             return;
@@ -826,41 +950,16 @@ public class DatabaseUtil {
         // Db/Driver support settings
         if (Debug.infoOn()) {
                 Debug.logInfo("Database Setting/Support Information (those with a * should be true):", module);
-            try {
-                Debug.logInfo("- supports transactions    [" + dbData.supportsTransactions() + "]*", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- supports transactions    [ DETECTION FAILED ]*", module);
-            }
-            try {
-                Debug.logInfo("- isolation None           [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_NONE) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- isolation None           [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- isolation ReadCommitted  [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_COMMITTED) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- isolation ReadCommitted  [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- isolation ReadUncommitted[" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- isolation ReadUncommitted[ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- isolation RepeatableRead [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_REPEATABLE_READ) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- isolation RepeatableRead [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- isolation Serializable   [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- isolation Serializable   [ DETECTION FAILED ]", module);
+            for (Detection detection: detections) {
+                String requiredFlag = detection.required ? "*" : "";
+                try {
+                    Object result = detection.method.invoke(dbData, detection.params);
+                    Debug.logInfo(String.format(goodFormatStr, detection.name, result, requiredFlag), module);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    Debug.logVerbose(e, module);
+                    Debug.logWarning(String.format(badFormatStr, detection.name, requiredFlag), module);
+                }
             }
             try {
                 Debug.logInfo("- default fetchsize        [" + con.createStatement().getFetchSize() + "]", module);
@@ -869,156 +968,6 @@ public class DatabaseUtil {
                 Debug.logWarning("- default fetchsize        [ DETECTION FAILED ]", module);
             }
             try {
-                Debug.logInfo("- forward only type        [" + dbData.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- forward only type        [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- scroll sensitive type    [" + dbData.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- scroll sensitive type    [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- scroll insensitive type  [" + dbData.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- scroll insensitive type  [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- is case sensitive        [" + dbData.supportsMixedCaseIdentifiers() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- is case sensitive        [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- stores LowerCase         [" + dbData.storesLowerCaseIdentifiers() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- stores LowerCase         [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- stores MixedCase         [" + dbData.storesMixedCaseIdentifiers() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- stores MixedCase         [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- stores UpperCase         [" + dbData.storesUpperCaseIdentifiers() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- stores UpperCase         [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- max table name length    [" + dbData.getMaxTableNameLength() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- max table name length    [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- max column name length   [" + dbData.getMaxColumnNameLength() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- max column name length   [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- max schema name length   [" + dbData.getMaxSchemaNameLength() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- max schema name length   [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- concurrent connections   [" + dbData.getMaxConnections() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- concurrent connections   [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- concurrent statements    [" + dbData.getMaxStatements() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- concurrent statements    [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- ANSI SQL92 Entry         [" + dbData.supportsANSI92EntryLevelSQL() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- ANSI SQL92 Entry         [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- ANSI SQL92 Intermediate  [" + dbData.supportsANSI92IntermediateSQL() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- ANSI SQL92 Intermediate  [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- ANSI SQL92 Full          [" + dbData.supportsANSI92FullSQL() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- ANSI SQL92 Full          [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- ODBC SQL Grammar Core    [" + dbData.supportsCoreSQLGrammar() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- ODBC SQL Grammar Core    [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- ODBC SQL Grammar Extended[" + dbData.supportsExtendedSQLGrammar() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- ODBC SQL Grammar Extended[ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- ODBC SQL Grammar Minimum [" + dbData.supportsMinimumSQLGrammar() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- ODBC SQL Grammar Minimum [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- outer joins              [" + dbData.supportsOuterJoins() + "]*", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- outer joins              [ DETECTION FAILED]*", module);
-            }
-            try {
-                Debug.logInfo("- limited outer joins      [" + dbData.supportsLimitedOuterJoins() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- limited outer joins      [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- full outer joins         [" + dbData.supportsFullOuterJoins() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- full outer joins         [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- group by                 [" + dbData.supportsGroupBy() + "]*", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- group by                 [ DETECTION FAILED ]*", module);
-            }
-            try {
-                Debug.logInfo("- group by not in select   [" + dbData.supportsGroupByUnrelated() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- group by not in select   [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- column aliasing          [" + dbData.supportsColumnAliasing() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- column aliasing          [ DETECTION FAILED ]", module);
-            }
-            try {
-                Debug.logInfo("- order by not in select   [" + dbData.supportsOrderByUnrelated() + "]", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- order by not in select   [ DETECTION FAILED ]", module);
-            }
-            try {
                 //this doesn't work in HSQLDB, other databases?
                 //crashed (vm-death) with MS SQL Server 2000, runs properly with MS SQL Server 2005
                 //Debug.logInfo("- named parameters         [" + dbData.supportsNamedParameters() + "]", module);
@@ -1027,18 +976,6 @@ public class DatabaseUtil {
                 Debug.logVerbose(e, module);
                 Debug.logWarning("- named parameters JDBC-3  [ DETECTION FAILED ]", module);
             }
-            try {
-                Debug.logInfo("- alter table add column   [" + dbData.supportsAlterTableWithAddColumn() + "]*", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- alter table add column   [ DETECTION FAILED ]*", module);
-            }
-            try {
-                Debug.logInfo("- non-nullable column      [" + dbData.supportsNonNullableColumns() + "]*", module);
-            } catch (Exception e) {
-                Debug.logVerbose(e, module);
-                Debug.logWarning("- non-nullable column      [ DETECTION FAILED ]*", module);
-            }
         }
     }
 
@@ -1153,6 +1090,17 @@ public class DatabaseUtil {
         return tableNames;
     }
 
+    private AbstractCountingCallable createPrimaryKeyFetcher(final DatabaseMetaData dbData, final String lookupSchemaName, final boolean needsUpperCase, final Map<String, Map<String, ColumnCheckInfo>> colInfo, final Collection<String> messages, final String curTable) {
+        return new AbstractCountingCallable(null, null) {
+            public AbstractCountingCallable call() throws Exception {
+                Debug.logInfo("Fetching primary keys for " + curTable, module);
+                ResultSet rsPks = dbData.getPrimaryKeys(null, lookupSchemaName, curTable);
+                count = checkPrimaryKeyInfo(rsPks, lookupSchemaName, needsUpperCase, colInfo, messages);
+                return this;
+            }
+        };
+    }
+
     public Map<String, Map<String, ColumnCheckInfo>> getColumnInfo(Set<String> tableNames, boolean getPks, Collection<String> messages) {
         // if there are no tableNames, don't even try to get the columns
         if (tableNames.size() == 0) {
@@ -1282,10 +1230,13 @@ public class DatabaseUtil {
                     }
                     if (pkCount == 0) {
                         Debug.logInfo("Searching in " + tableNames.size() + " tables for primary key fields ...", module);
+                        List<Future<AbstractCountingCallable>> pkFetcherFutures = FastList.newInstance();
                         for (String curTable: tableNames) {
                             curTable = curTable.substring(curTable.indexOf('.') + 1); //cut off schema name
-                            ResultSet rsPks = dbData.getPrimaryKeys(null, lookupSchemaName, curTable);
-                            pkCount += checkPrimaryKeyInfo(rsPks, lookupSchemaName, needsUpperCase, colInfo, messages);
+                            pkFetcherFutures.add(submitWork(createPrimaryKeyFetcher(dbData, lookupSchemaName, needsUpperCase, colInfo, messages, curTable)));
+                        }
+                        for (AbstractCountingCallable pkFetcherCallable: ExecutionPool.getAllFutures(pkFetcherFutures)) {
+                            pkCount += pkFetcherCallable.updateData(messages);
                         }
                     }
 
@@ -1627,6 +1578,66 @@ public class DatabaseUtil {
         return indexInfo;
     }
 
+    private class CreateTableCallable implements Callable<CreateTableCallable> {
+        private final ModelEntity entity;
+        private final Map<String, ModelEntity> modelEntities;
+        private final String tableName;
+        private String message;
+        private boolean success;
+
+        protected CreateTableCallable(ModelEntity entity, Map<String, ModelEntity> modelEntities, String tableName) {
+            this.entity = entity;
+            this.modelEntities = modelEntities;
+            this.tableName = tableName;
+        }
+
+        public CreateTableCallable call() throws Exception {
+            String errMsg = createTable(entity, modelEntities, false);
+            if (UtilValidate.isNotEmpty(errMsg)) {
+                this.success = false;
+                this.message = "Could not create table [" + tableName + "]: " + errMsg;
+                Debug.logError(this.message, module);
+            } else {
+                this.success = true;
+                this.message = "Created table [" + tableName + "]";
+                Debug.logImportant(this.message, module);
+            }
+            return this;
+        }
+
+        protected void updateData(Collection<String> messages, List<ModelEntity> entitiesAdded) {
+            if (this.success) {
+                entitiesAdded.add(entity);
+                if (messages != null) {
+                    messages.add(this.message);
+                }
+            } else {
+                if (messages != null) {
+                    messages.add(this.message);
+                }
+            }
+        }
+    }
+
+    private abstract class AbstractCountingCallable implements Callable<AbstractCountingCallable> {
+        protected final ModelEntity entity;
+        protected final Map<String, ModelEntity> modelEntities;
+        protected final List<String> messages = FastList.newInstance();
+        protected int count;
+
+        protected AbstractCountingCallable(ModelEntity entity, Map<String, ModelEntity> modelEntities) {
+            this.entity = entity;
+            this.modelEntities = modelEntities;
+        }
+
+        protected int updateData(Collection<String> messages) {
+            if (messages != null && UtilValidate.isNotEmpty(this.messages)) {
+                messages.addAll(messages);
+            }
+            return count;
+        }
+    }
+
     /* ====================================================================== */
 
     /* ====================================================================== */