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; + } + } + /* ====================================================================== */ /* ====================================================================== */ |
Free forum by Nabble | Edit this page |