Author: jonesde
Date: Wed Mar 10 10:29:30 2010 New Revision: 921290 URL: http://svn.apache.org/viewvc?rev=921290&view=rev Log: Initial implementation from patch in Jira #OFBIZ-3540 including my initial work plus the improvement that Scott added in that issue Added: ofbiz/branches/multitenant20100310/framework/entity/data/ ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml (with props) ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml (with props) ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java (with props) Modified: ofbiz/branches/multitenant20100310/framework/common/config/CommonUiLabels.xml ofbiz/branches/multitenant20100310/framework/common/config/SecurityextUiLabels.xml ofbiz/branches/multitenant20100310/framework/common/webcommon/login.ftl ofbiz/branches/multitenant20100310/framework/entity/config/entityengine.xml ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitymodel.xml ofbiz/branches/multitenant20100310/framework/entity/ofbiz-component.xml ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/Delegator.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/GenericDelegator.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/ConnectionFactoryInterface.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/DBCPConnectionFactory.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/MinervaConnectionFactory.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperFactory.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/jdbc/ConnectionFactory.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/jdbc/DatabaseUtil.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/jdbc/SQLProcessor.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/model/ModelGroupReader.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/transaction/DumbFactory.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/transaction/JNDIFactory.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/transaction/TransactionFactory.java ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/transaction/TransactionFactoryInterface.java ofbiz/branches/multitenant20100310/framework/entityext/entitydef/entitymodel.xml ofbiz/branches/multitenant20100310/framework/entityext/ofbiz-component.xml ofbiz/branches/multitenant20100310/framework/entityext/src/org/ofbiz/entityext/data/EntityDataLoadContainer.java ofbiz/branches/multitenant20100310/framework/entityext/src/org/ofbiz/entityext/data/EntityDataServices.java ofbiz/branches/multitenant20100310/framework/entityext/src/org/ofbiz/entityext/eca/DelegatorEcaHandler.java ofbiz/branches/multitenant20100310/framework/geronimo/src/org/ofbiz/geronimo/GeronimoTransactionFactory.java ofbiz/branches/multitenant20100310/framework/security/entitydef/entitymodel.xml ofbiz/branches/multitenant20100310/framework/service/src/org/ofbiz/service/GenericDispatcher.java ofbiz/branches/multitenant20100310/framework/service/src/org/ofbiz/service/job/PersistedServiceJob.java ofbiz/branches/multitenant20100310/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java ofbiz/branches/multitenant20100310/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java ofbiz/branches/multitenant20100310/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java ofbiz/branches/multitenant20100310/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java ofbiz/branches/multitenant20100310/framework/webapp/src/org/ofbiz/webapp/stats/ServerHitBin.java ofbiz/branches/multitenant20100310/framework/webapp/src/org/ofbiz/webapp/stats/VisitHandler.java ofbiz/branches/multitenant20100310/framework/webtools/webapp/webtools/WEB-INF/actions/entity/EntityMaint.groovy ofbiz/branches/multitenant20100310/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java Modified: ofbiz/branches/multitenant20100310/framework/common/config/CommonUiLabels.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/common/config/CommonUiLabels.xml?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/common/config/CommonUiLabels.xml (original) +++ ofbiz/branches/multitenant20100310/framework/common/config/CommonUiLabels.xml Wed Mar 10 10:29:30 2010 @@ -7075,6 +7075,9 @@ <value xml:lang="nl">Belasting</value> <value xml:lang="zh">ç¨</value> </property> + <property key="CommonTenantId"> + <value xml:lang="en">Tenant ID</value> + </property> <property key="CommonTelephoneAbbr"> <value xml:lang="ar">ÙاتÙ</value> <value xml:lang="de">Tel</value> Modified: ofbiz/branches/multitenant20100310/framework/common/config/SecurityextUiLabels.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/common/config/SecurityextUiLabels.xml?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/common/config/SecurityextUiLabels.xml (original) +++ ofbiz/branches/multitenant20100310/framework/common/config/SecurityextUiLabels.xml Wed Mar 10 10:29:30 2010 @@ -177,7 +177,7 @@ </property> <property key="loginevents.unable_to_login_this_application"> <value xml:lang="de">Anmeldung bei der Anwendung nicht erfolgreich</value> - <value xml:lang="en">unable to login this application</value> + <value xml:lang="en">You cannot login to this application</value> <value xml:lang="es">No puedo conectarse a esta aplicación (faltan permisos)</value> <value xml:lang="fr">Impossible de se connecter à cette application.</value> <value xml:lang="it">L'autenticazione per questa applicazione non è stata completata (permessi non sufficienti).</value> @@ -187,6 +187,9 @@ <value xml:lang="th">à¹à¸¡à¹à¸ªà¸²à¸¡à¸²à¸£à¸à¸¥à¸à¸à¸à¸´à¸à¹à¸à¹à¸²à¸ªà¸¹à¹à¹à¸à¸£à¹à¸à¸£à¸¡à¸à¸£à¸°à¸¢à¸¸à¸à¸à¹à¸à¸µà¹</value> <value xml:lang="zh">æ æ³ç»å½è¿ä¸ªåºç¨ç¨åº</value> </property> + <property key="loginevents.unable_to_login_tenant"> + <value xml:lang="en">You cannot login to this tenant</value> + </property> <property key="loginevents.user_already_logged_in"> <value xml:lang="de">Dieser User ist bereits eingeloggt.</value> <value xml:lang="en">This user is already logged in.</value> Modified: ofbiz/branches/multitenant20100310/framework/common/webcommon/login.ftl URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/common/webcommon/login.ftl?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/common/webcommon/login.ftl (original) +++ ofbiz/branches/multitenant20100310/framework/common/webcommon/login.ftl Wed Mar 10 10:29:30 2010 @@ -42,6 +42,10 @@ under the License. <td><input type="password" name="PASSWORD" value="" size="20"/></td> </tr> <tr> + <td class="label">${uiLabelMap.CommonTenantId}</td> + <td><input type="text" name="tenantId" value="${parameters.tenantId?if_exists}" size="20"/></td> + </tr> + <tr> <td colspan="2" align="center"> <input type="submit" value="${uiLabelMap.CommonLogin}"/> </td> Modified: ofbiz/branches/multitenant20100310/framework/entity/config/entityengine.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/config/entityengine.xml?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/config/entityengine.xml (original) +++ ofbiz/branches/multitenant20100310/framework/entity/config/entityengine.xml Wed Mar 10 10:29:30 2010 @@ -52,19 +52,19 @@ access. For a detailed description see t <delegator name="default" entity-model-reader="main" entity-group-reader="main" entity-eca-reader="main" distributed-cache-clear-enabled="false"> <group-map group-name="org.ofbiz" datasource-name="localderby"/> <group-map group-name="org.ofbiz.olap" datasource-name="localderbyolap"/> + <group-map group-name="org.ofbiz.tenant" datasource-name="localderbytenant"/> </delegator> <delegator name="default-no-eca" entity-model-reader="main" entity-group-reader="main" entity-eca-reader="main" entity-eca-enabled="false" distributed-cache-clear-enabled="false"> <group-map group-name="org.ofbiz" datasource-name="localderby"/> <group-map group-name="org.ofbiz.olap" datasource-name="localderbyolap"/> + <group-map group-name="org.ofbiz.tenant" datasource-name="localderbytenant"/> </delegator> <!-- be sure that your default delegator (or the one you use) uses the same datasource for test. You must run "ant run-install" before running "ant run-tests" --> <delegator name="test" entity-model-reader="main" entity-group-reader="main" entity-eca-reader="main"> <group-map group-name="org.ofbiz" datasource-name="localderby"/> <group-map group-name="org.ofbiz.olap" datasource-name="localderbyolap"/> - </delegator> - <delegator name="other" entity-model-reader="main" entity-group-reader="main" entity-eca-reader="main"> - <group-map group-name="org.ofbiz" datasource-name="localpostgres"/> + <group-map group-name="org.ofbiz.tenant" datasource-name="localderbytenant"/> </delegator> <!-- need to at least define a name for each component to use --> @@ -218,7 +218,31 @@ access. For a detailed description see t time-between-eviction-runs-millis="600000"/> <!-- <jndi-jdbc jndi-server-name="localjndi" jndi-name="java:/DerbyDataSource" isolation-level="ReadCommitted"/> --> </datasource> - + <datasource name="localderbytenant" + helper-class="org.ofbiz.entity.datasource.GenericHelperDAO" + schema-name="OFBIZ" + field-type-name="derby" + check-on-start="true" + add-missing-on-start="true" + use-pk-constraint-names="false" + use-indices-unique="false" + alias-view-columns="false"> + <read-data reader-name="seed"/> + <read-data reader-name="seed-initial"/> + <read-data reader-name="demo"/> + <read-data reader-name="ext"/> + <inline-jdbc + jdbc-driver="org.apache.derby.jdbc.EmbeddedDriver" + jdbc-uri="jdbc:derby:ofbiztenant;create=true" + jdbc-username="ofbiz" + jdbc-password="ofbiz" + isolation-level="ReadCommitted" + pool-minsize="2" + pool-maxsize="250" + time-between-eviction-runs-millis="600000"/> + <!-- <jndi-jdbc jndi-server-name="localjndi" jndi-name="java:/DerbyDataSource" isolation-level="ReadCommitted"/> --> + </datasource> + <datasource name="localcloudscape" helper-class="org.ofbiz.entity.datasource.GenericHelperDAO" field-type-name="cloudscape" Added: ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml?rev=921290&view=auto ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml (added) +++ ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml Wed Mar 10 10:29:30 2010 @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<entity-engine-xml> + <!-- to prep the databases for these (just like the main databases need to be prepped) run something like: + java -Xmx512m -XX:MaxPermSize=128m -jar ofbiz.jar -install -delegator=default#DEMO1 + --> + <Tenant tenantId="DEMO1" tenantName="Demo Tenant One"/> + <TenantDataSource tenantId="DEMO1" entityGroupName="org.ofbiz" + jdbcUri="jdbc:derby:ofbiz_DEMO1;create=true" jdbcUsername="ofbiz" jdbcPassword="ofbiz"/> + <TenantDataSource tenantId="DEMO1" entityGroupName="org.ofbiz.olap" + jdbcUri="jdbc:derby:ofbizolap_DEMO1;create=true" jdbcUsername="ofbiz" jdbcPassword="ofbiz"/> + <!-- the org.ofbiz.tenant URI should be the same for ALL tenants, so don't create a TenantDataSource record for it, it will be ignored anyway --> + <TenantUserLogin tenantId="DEMO1" userLoginId="admin" fromDate="2001-05-13 00:00:00.000" thruDate="" isManager="Y"/> + + <Tenant tenantId="DEMO2" tenantName="Demo Tenant Two"/> + <TenantDataSource tenantId="DEMO2" entityGroupName="org.ofbiz" + jdbcUri="jdbc:derby:ofbiz_DEMO2;create=true" jdbcUsername="ofbiz" jdbcPassword="ofbiz"/> + <TenantDataSource tenantId="DEMO2" entityGroupName="org.ofbiz.olap" + jdbcUri="jdbc:derby:ofbizolap_DEMO2;create=true" jdbcUsername="ofbiz" jdbcPassword="ofbiz"/> + <TenantUserLogin tenantId="DEMO2" userLoginId="admin" fromDate="2001-05-13 00:00:00.000" thruDate="" isManager="N"/> +</entity-engine-xml> Propchange: ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/branches/multitenant20100310/framework/entity/data/TenantDemoData.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml?rev=921290&view=auto ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml (added) +++ ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml Wed Mar 10 10:29:30 2010 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<entitygroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/entitygroup.xsd"> + + <!-- ========================================================= --> + <!-- org.ofbiz.entity.tenant --> + <!-- ========================================================= --> + <entity-group group="org.ofbiz.tenant" entity="Tenant"/> + <entity-group group="org.ofbiz.tenant" entity="TenantDataSource"/> + <entity-group group="org.ofbiz.tenant" entity="TenantUserLogin"/> +</entitygroup> Propchange: ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitygroup.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Modified: ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitymodel.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitymodel.xml?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitymodel.xml (original) +++ ofbiz/branches/multitenant20100310/framework/entity/entitydef/entitymodel.xml Wed Mar 10 10:29:30 2010 @@ -35,6 +35,7 @@ under the License. <!-- - org.ofbiz.entity.audit --> <!-- - org.ofbiz.entity.crypto --> <!-- - org.ofbiz.entity.sequence --> + <!-- org.ofbiz.entity.tenant --> <!-- ========================================================= --> <entity entity-name="EntityAuditLog" package-name="org.ofbiz.entity.audit" title="Entity Audit Log"> @@ -59,4 +60,44 @@ under the License. <field name="seqId" type="numeric"></field> <prim-key field="seqName"/> </entity> + + <!-- ========================================================= --> + <!-- org.ofbiz.entity.tenant --> + <!-- ========================================================= --> + + <entity entity-name="Tenant" package-name="org.ofbiz.entity.tenant"> + <field name="tenantId" type="id-ne"/> + <field name="tenantName" type="name"/> + <prim-key field="tenantId"/> + </entity> + <entity entity-name="TenantDataSource" package-name="org.ofbiz.entity.tenant"> + <description> + There should be one record for each tenant and each group-map for the active delegator. + The jdbc fields will override the datasource -> inline-jdbc values for the per-tenant delegator. + </description> + <field name="tenantId" type="id-ne"/> + <field name="entityGroupName" type="name"/> + <field name="jdbcUri" type="long-varchar"/> + <field name="jdbcUsername" type="long-varchar"/> + <field name="jdbcPassword" type="long-varchar"/> + <prim-key field="tenantId"/> + <prim-key field="entityGroupName"/> + <relation type="one" fk-name="TNTDTSRC_TNT" rel-entity-name="Tenant"> + <key-map field-name="tenantId"/> + </relation> + </entity> + <entity entity-name="TenantUserLogin" package-name="org.ofbiz.entity.tenant"> + <field name="tenantId" type="id-ne"/> + <field name="userLoginId" type="name"/> + <field name="fromDate" type="date-time"/> + <field name="thruDate" type="date-time"/> + <field name="isManager" type="indicator"/> + <prim-key field="tenantId"/> + <prim-key field="userLoginId"/> + <prim-key field="fromDate"/> + <relation type="one" fk-name="TNTUSRLGN_TNT" rel-entity-name="Tenant"> + <key-map field-name="tenantId"/> + </relation> + <!-- NOTE: there is no FK to the UserLogin entity, which is in a higher-level component, and would normally be in a separate database --> + </entity> </entitymodel> Modified: ofbiz/branches/multitenant20100310/framework/entity/ofbiz-component.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/ofbiz-component.xml?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/ofbiz-component.xml (original) +++ ofbiz/branches/multitenant20100310/framework/entity/ofbiz-component.xml Wed Mar 10 10:29:30 2010 @@ -27,10 +27,14 @@ under the License. <classpath type="jar" location="lib/*"/> <classpath type="jar" location="lib/jdbc/*"/> <classpath type="jar" location="build/lib/*"/> + <entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel.xml"/> - + <entity-resource type="group" reader-name="main" loader="main" location="entitydef/entitygroup.xml"/> + <!-- these are for unit testing --> <entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel_test.xml"/> + <entity-resource type="data" reader-name="demo" loader="main" location="data/TenantDemoData.xml"/> + <test-suite loader="main" location="testdef/entitytests.xml"/> </ofbiz-component> Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/Delegator.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/Delegator.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/Delegator.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/Delegator.java Wed Mar 10 10:29:30 2010 @@ -29,6 +29,7 @@ import javax.xml.parsers.ParserConfigura import org.ofbiz.entity.cache.Cache; import org.ofbiz.entity.condition.EntityCondition; import org.ofbiz.entity.datasource.GenericHelper; +import org.ofbiz.entity.datasource.GenericHelperInfo; import org.ofbiz.entity.eca.EntityEcaHandler; import org.ofbiz.entity.model.DynamicViewEntity; import org.ofbiz.entity.model.ModelEntity; @@ -504,6 +505,8 @@ public interface Delegator { public Cache getCache(); public String getDelegatorName(); + public String getDelegatorBaseName(); + public String getDelegatorTenantId(); public <T> EntityEcaHandler<T> getEntityEcaHandler(); @@ -599,6 +602,8 @@ public interface Delegator { */ public String getGroupHelperName(String groupName); + public GenericHelperInfo getGroupHelperInfo(String entityGroupName); + /** * Gets the instance of ModelEntity that corresponds to this delegator and * the specified entityName Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java Wed Mar 10 10:29:30 2010 @@ -47,7 +47,7 @@ public class DelegatorFactoryImpl extend if (delegator != null) { GenericDelegator.delegatorCache.put(delegatorName, delegator); } else { - Debug.logError("Could not create delegator with name " + delegatorName + ", constructor failed (got null value) not sure why/how.", module); + Debug.logError("Could not create delegator with name " + delegatorName + ", constructor failed (got null value).", module); } } } Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/GenericDelegator.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/GenericDelegator.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/GenericDelegator.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/GenericDelegator.java Wed Mar 10 10:29:30 2010 @@ -25,7 +25,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -55,6 +54,7 @@ import org.ofbiz.entity.config.Delegator import org.ofbiz.entity.config.EntityConfigUtil; import org.ofbiz.entity.datasource.GenericHelper; import org.ofbiz.entity.datasource.GenericHelperFactory; +import org.ofbiz.entity.datasource.GenericHelperInfo; import org.ofbiz.entity.eca.EntityEcaHandler; import org.ofbiz.entity.model.DynamicViewEntity; import org.ofbiz.entity.model.ModelEntity; @@ -98,7 +98,11 @@ public class GenericDelegator implements /** the delegatorCache will now be a HashMap, allowing reload of definitions, * but the delegator will always be the same object for the given name */ public static Map<String, GenericDelegator> delegatorCache = FastMap.newInstance(); - protected String delegatorName = null; + protected String delegatorBaseName = null; + protected String delegatorFullName = null; + protected String delegatorTenantId = null; + private String originalDelegatorName = null; + protected DelegatorInfo delegatorInfo = null; protected Cache cache = null; @@ -122,8 +126,6 @@ public class GenericDelegator implements private volatile LinkedBlockingDeque<TestOperation> testOperations = null; private enum OperationType {INSERT, UPDATE, DELETE}; - private String originalDelegatorName = null; - /** @deprecated Use Delegator delegator = DelegatorFactory.getDelegator(delegatorName); * @param delegatorName * @return the configured delegator @@ -219,14 +221,23 @@ public class GenericDelegator implements protected GenericDelegator() {} /** Only allow creation through the factory method */ - protected GenericDelegator(String delegatorName) throws GenericEntityException { - //if (Debug.infoOn()) Debug.logInfo("Creating new Delegator with name \"" + delegatorName + "\".", module); + 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); + GenericValue tenant = baseDelegator.findOne("Tenant", true, "tenantId", this.delegatorTenantId); + if (tenant == null) { + 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); - this.delegatorName = delegatorName; - this.modelReader = ModelReader.getModelReader(delegatorName); - this.modelGroupReader = ModelGroupReader.getModelGroupReader(delegatorName); - - cache = new Cache(delegatorName); + cache = new Cache(delegatorFullName); // do the entity model check List<String> warningList = FastList.newInstance(); @@ -240,28 +251,27 @@ public class GenericDelegator implements } // initialize helpers by group - Set<String> groupNames = getModelGroupReader().getGroupNames(delegatorName); - Iterator<String> groups = UtilMisc.toIterator(groupNames); - while (groups != null && groups.hasNext()) { - String groupName = groups.next(); - String helperName = this.getGroupHelperName(groupName); + Set<String> groupNames = getModelGroupReader().getGroupNames(delegatorBaseName); + for (String groupName: groupNames) { + GenericHelperInfo helperInfo = this.getGroupHelperInfo(groupName); + String helperBaseName = helperInfo.getHelperBaseName(); - if (Debug.infoOn()) Debug.logInfo("Delegator \"" + delegatorName + "\" initializing helper \"" + - helperName + "\" for entity group \"" + groupName + "\".", module); + if (Debug.infoOn()) Debug.logInfo("Delegator \"" + delegatorFullName + "\" initializing helper \"" + + helperBaseName + "\" for entity group \"" + groupName + "\".", module); TreeSet<String> helpersDone = new TreeSet<String>(); - if (UtilValidate.isNotEmpty(helperName)) { + if (UtilValidate.isNotEmpty(helperInfo.getHelperFullName())) { // make sure each helper is only loaded once - if (helpersDone.contains(helperName)) { - if (Debug.infoOn()) Debug.logInfo("Helper \"" + helperName + "\" already initialized, not re-initializing.", module); + if (helpersDone.contains(helperInfo.getHelperFullName())) { + if (Debug.infoOn()) Debug.logInfo("Helper \"" + helperInfo.getHelperFullName() + "\" already initialized, not re-initializing.", module); continue; } - helpersDone.add(helperName); + helpersDone.add(helperInfo.getHelperFullName()); // pre-load field type defs, the return value is ignored - ModelFieldTypeReader.getModelFieldTypeReader(helperName); + ModelFieldTypeReader.getModelFieldTypeReader(helperBaseName); // get the helper and if configured, do the datasource check - GenericHelper helper = GenericHelperFactory.getHelper(helperName); + GenericHelper helper = GenericHelperFactory.getHelper(helperInfo); - DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperName); + 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 { @@ -275,9 +285,10 @@ public class GenericDelegator implements // 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 // put the delegator in the master Map by its name - GenericDelegator.delegatorCache.put(delegatorName, this); + // TODO: we should find a better way to do this since putting the delegator in the cache before it is completely setup may cause errors with multiple threads + GenericDelegator.delegatorCache.put(delegatorFullName, this); - // setup the crypto class + // setup the crypto class; this also after the delegator is in the cache otherwise we get infinite recursion this.crypto = new EntityCrypto(this); //time to do some tricks with manual class loading that resolves circular dependencies, like calling services... @@ -304,12 +315,24 @@ public class GenericDelegator implements Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " does not implement the DistributedCacheClear interface, distributed cache clearing will be disabled", module); } } else { - Debug.logInfo("Distributed Cache Clear System disabled for delegator [" + delegatorName + "]", module); + Debug.logInfo("Distributed Cache Clear System disabled for delegator [" + delegatorFullName + "]", module); } // setup the Entity ECA Handler initEntityEcaHandler(); } + + protected void setDelegatorNames(String delegatorFullName) { + this.delegatorFullName = delegatorFullName; + + int hashSymbolIndex = delegatorFullName.indexOf('#'); + if (hashSymbolIndex == -1) { + this.delegatorBaseName = delegatorFullName; + } else { + this.delegatorBaseName = delegatorFullName.substring(0, hashSymbolIndex); + this.delegatorTenantId = delegatorFullName.substring(hashSymbolIndex + 1); + } + } /* (non-Javadoc) * @see org.ofbiz.entity.Delegator#initEntityEcaHandler() @@ -334,7 +357,7 @@ public class GenericDelegator implements Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " does not implement the EntityEcaHandler interface, Entity ECA Rules will be disabled", module); } } else { - Debug.logInfo("Entity ECA Handler disabled for delegator [" + delegatorName + "]", module); + Debug.logInfo("Entity ECA Handler disabled for delegator [" + delegatorFullName + "]", module); } } @@ -342,19 +365,33 @@ public class GenericDelegator implements * @see org.ofbiz.entity.Delegator#getDelegatorName() */ public String getDelegatorName() { - return this.delegatorName; + return this.delegatorFullName; + } + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#getDelegatorBaseName() + */ + public String getDelegatorBaseName() { + return this.delegatorBaseName; + } + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#getDelegatorBaseName() + */ + public String getDelegatorTenantId() { + return this.delegatorTenantId; } /* (non-Javadoc) * @see org.ofbiz.entity.Delegator#getOriginalDelegatorName() */ public String getOriginalDelegatorName() { - return this.originalDelegatorName == null ? this.delegatorName : this.originalDelegatorName; + return this.originalDelegatorName == null ? this.delegatorFullName : this.originalDelegatorName; } protected DelegatorInfo getDelegatorInfo() { if (this.delegatorInfo == null) { - this.delegatorInfo = EntityConfigUtil.getDelegatorInfo(this.delegatorName); + this.delegatorInfo = EntityConfigUtil.getDelegatorInfo(this.delegatorBaseName); } return this.delegatorInfo; } @@ -389,7 +426,7 @@ public class GenericDelegator implements * @see org.ofbiz.entity.Delegator#getEntityGroupName(java.lang.String) */ public String getEntityGroupName(String entityName) { - return getModelGroupReader().getEntityGroupName(entityName, getOriginalDelegatorName()); + return getModelGroupReader().getEntityGroupName(entityName, this.delegatorBaseName); } /* (non-Javadoc) @@ -402,7 +439,7 @@ public class GenericDelegator implements // add all entities with no group name to the Set Set<String> allEntityNames = this.getModelReader().getEntityNames(); for (String entityName: allEntityNames) { - if (this.getDelegatorInfo().defaultGroupName.equals(getModelGroupReader().getEntityGroupName(entityName, getDelegatorName()))) { + if (this.getDelegatorInfo().defaultGroupName.equals(getModelGroupReader().getEntityGroupName(entityName, this.delegatorBaseName))) { entityNameSet.add(entityName); } } @@ -442,6 +479,42 @@ public class GenericDelegator implements return this.getDelegatorInfo().groupMap.get(groupName); } + public GenericHelperInfo getGroupHelperInfo(String entityGroupName) { + if (entityGroupName == null) return null; + String helperBaseName = this.getGroupHelperName(entityGroupName); + 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 + // NOTE: always use the base delegator for this to avoid problems when this is being initialized + Delegator baseDelegator = DelegatorFactory.getDelegator(this.delegatorBaseName); + GenericValue tenantDataSource = baseDelegator.findOne("TenantDataSource", true, "tenantId", this.delegatorTenantId, "entityGroupName", entityGroupName); + if (tenantDataSource != null) { + helperInfo.setOverrideJdbcUri(tenantDataSource.getString("jdbcUri")); + 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); + } + } 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) */ @@ -462,10 +535,10 @@ public class GenericDelegator implements * @see org.ofbiz.entity.Delegator#getEntityHelper(java.lang.String) */ public GenericHelper getEntityHelper(String entityName) throws GenericEntityException { - String helperName = getEntityHelperName(entityName); + GenericHelperInfo helperInfo = getEntityHelperInfo(entityName); - if (UtilValidate.isNotEmpty(helperName)) { - return GenericHelperFactory.getHelper(helperName); + if (helperInfo != null) { + return GenericHelperFactory.getHelper(helperInfo); } else { throw new GenericEntityException("There is no datasource (Helper) configured for the entity-group [" + this.getEntityGroupName(entityName) + "]; was trying to find datesource (helper) for entity [" + entityName + "]"); } @@ -728,7 +801,14 @@ public class GenericDelegator implements } catch (GenericEntityException e) { // see if this was caused by an existing record before resetting the sequencer and trying again // NOTE: use the helper directly so ECA rules, etc won't be run - GenericValue existingValue = helper.findByPrimaryKey(value.getPrimaryKey()); + + GenericValue existingValue = null; + try { + existingValue = helper.findByPrimaryKey(value.getPrimaryKey()); + } catch (GenericEntityException e1) { + // ignore this error, if not found it'll probably be a GenericEntityNotFoundException + // it is important to not let this get thrown because it will mask the original exception + } if (existingValue == null) { throw e; } else { @@ -763,7 +843,7 @@ public class GenericDelegator implements return value; } catch (GenericEntityException e) { - String errMsg = "Failure in create operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction."; + String errMsg = "Failure in createSetNextSeqId operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction."; Debug.logError(e, errMsg, module); try { // only rollback the transaction if we started one... @@ -1682,21 +1762,21 @@ public class GenericDelegator implements // from the delegator level this is complicated because different GenericPK // objects in the list may correspond to different helpers - Map<String, List<GenericPK>> pksPerHelper = FastMap.newInstance(); + Map<String, List<GenericPK>> pksPerGroup = FastMap.newInstance(); for (GenericPK curPK: primaryKeys) { - String helperName = this.getEntityHelperName(curPK.getEntityName()); - List<GenericPK> pks = pksPerHelper.get(helperName); + String groupName = this.getEntityGroupName(curPK.getEntityName()); + List<GenericPK> pks = pksPerGroup.get(groupName); if (pks == null) { pks = FastList.newInstance(); - pksPerHelper.put(helperName, pks); + pksPerGroup.put(groupName, pks); } pks.add(curPK); } - for (Map.Entry<String, List<GenericPK>> curEntry: pksPerHelper.entrySet()) { - String helperName = curEntry.getKey(); - GenericHelper helper = GenericHelperFactory.getHelper(helperName); + for (Map.Entry<String, List<GenericPK>> curEntry: pksPerGroup.entrySet()) { + String groupName = curEntry.getKey(); + GenericHelper helper = GenericHelperFactory.getHelper(this.getGroupHelperInfo(groupName)); List<GenericValue> values = helper.findAllByPrimaryKeys(curEntry.getValue()); results.addAll(values); @@ -1740,7 +1820,7 @@ public class GenericDelegator implements // from the delegator level this is complicated because different GenericPK // objects in the list may correspond to different helpers - Map<String, List<GenericPK>> pksPerHelper = FastMap.newInstance(); + Map<String, List<GenericPK>> pksPerGroup = FastMap.newInstance(); for (GenericPK curPK: primaryKeys) { GenericValue value = this.getFromPrimaryKeyCache(curPK); @@ -1749,20 +1829,20 @@ public class GenericDelegator implements results.add(value); } else { // is not in the cache, so put in a list for a call to the helper - String helperName = this.getEntityHelperName(curPK.getEntityName()); - List<GenericPK> pks = pksPerHelper.get(helperName); + String groupName = this.getEntityGroupName(curPK.getEntityName()); + List<GenericPK> pks = pksPerGroup.get(groupName); if (pks == null) { pks = FastList.newInstance(); - pksPerHelper.put(helperName, pks); + pksPerGroup.put(groupName, pks); } pks.add(curPK); } } - for (Map.Entry<String, List<GenericPK>> curEntry: pksPerHelper.entrySet()) { - String helperName = curEntry.getKey(); - GenericHelper helper = GenericHelperFactory.getHelper(helperName); + for (Map.Entry<String, List<GenericPK>> curEntry: pksPerGroup.entrySet()) { + String groupName = curEntry.getKey(); + GenericHelper helper = GenericHelperFactory.getHelper(this.getGroupHelperInfo(groupName)); List<GenericValue> values = helper.findAllByPrimaryKeys(curEntry.getValue()); this.putAllInPrimaryKeyCache(values); @@ -3155,14 +3235,14 @@ public class GenericDelegator implements /* (non-Javadoc) * @see org.ofbiz.entity.Delegator#cloneDelegator(java.lang.String) */ - public GenericDelegator cloneDelegator(String delegatorName) { + public GenericDelegator cloneDelegator(String delegatorFullName) { // creates an exact clone of the delegator; except for the sequencer // note that this will not be cached and should be used only when // needed to change something for single instance (use). GenericDelegator newDelegator = new GenericDelegator(); newDelegator.modelReader = this.modelReader; newDelegator.modelGroupReader = this.modelGroupReader; - newDelegator.delegatorName = delegatorName; + newDelegator.setDelegatorNames(UtilValidate.isNotEmpty(delegatorFullName) ? delegatorFullName : this.delegatorFullName); newDelegator.delegatorInfo = this.delegatorInfo; newDelegator.cache = this.cache; newDelegator.andCacheFieldSets = this.andCacheFieldSets; @@ -3182,7 +3262,7 @@ public class GenericDelegator implements * @see org.ofbiz.entity.Delegator#cloneDelegator() */ public GenericDelegator cloneDelegator() { - return this.cloneDelegator(this.delegatorName); + return this.cloneDelegator(this.delegatorFullName); } /* (non-Javadoc) Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/ConnectionFactoryInterface.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/ConnectionFactoryInterface.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/ConnectionFactoryInterface.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/ConnectionFactoryInterface.java Wed Mar 10 10:29:30 2010 @@ -23,12 +23,13 @@ import java.sql.SQLException; import org.w3c.dom.Element; import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.datasource.GenericHelperInfo; /** * ConnectionFactoryInterface */ public interface ConnectionFactoryInterface { - public Connection getConnection(String helperName, Element configElement) throws SQLException, GenericEntityException; + public Connection getConnection(GenericHelperInfo helperInfo, Element configElement) throws SQLException, GenericEntityException; public void closeAll(); } Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/DBCPConnectionFactory.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/DBCPConnectionFactory.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/DBCPConnectionFactory.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/DBCPConnectionFactory.java Wed Mar 10 10:29:30 2010 @@ -28,6 +28,7 @@ import org.apache.commons.pool.impl.Gene import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.datasource.GenericHelperInfo; import org.ofbiz.entity.transaction.TransactionFactory; import org.w3c.dom.Element; @@ -48,24 +49,26 @@ public class DBCPConnectionFactory imple public static final String module = DBCPConnectionFactory.class.getName(); protected static Map<String, ManagedDataSource> dsCache = FastMap.newInstance(); - public Connection getConnection(String helperName, Element jdbcElement) throws SQLException, GenericEntityException { - ManagedDataSource mds = dsCache.get(helperName); + public Connection getConnection(GenericHelperInfo helperInfo, Element jdbcElement) throws SQLException, GenericEntityException { + ManagedDataSource mds = dsCache.get(helperInfo.getHelperFullName()); if (mds != null) { - return TransactionFactory.getCursorConnection(helperName, mds.getConnection()); + return TransactionFactory.getCursorConnection(helperInfo, mds.getConnection()); } synchronized (DBCPConnectionFactory.class) { - mds = dsCache.get(helperName); + mds = dsCache.get(helperInfo.getHelperFullName()); if (mds != null) { - return TransactionFactory.getCursorConnection(helperName, mds.getConnection()); + return TransactionFactory.getCursorConnection(helperInfo, mds.getConnection()); } // connection properties TransactionManager txMgr = TransactionFactory.getTransactionManager(); String driverName = jdbcElement.getAttribute("jdbc-driver"); - String dbUri = jdbcElement.getAttribute("jdbc-uri"); - String dbUser = jdbcElement.getAttribute("jdbc-username"); - String dbPass = jdbcElement.getAttribute("jdbc-password"); + + + String jdbcUri = UtilValidate.isNotEmpty(helperInfo.getOverrideJdbcUri()) ? helperInfo.getOverrideJdbcUri() : jdbcElement.getAttribute("jdbc-uri"); + String jdbcUsername = UtilValidate.isNotEmpty(helperInfo.getOverrideUsername()) ? helperInfo.getOverrideUsername() : jdbcElement.getAttribute("jdbc-username"); + String jdbcPassword = UtilValidate.isNotEmpty(helperInfo.getOverridePassword()) ? helperInfo.getOverridePassword() : jdbcElement.getAttribute("jdbc-password"); // pool settings int maxSize, minSize, timeBetweenEvictionRunsMillis; @@ -111,11 +114,11 @@ public class DBCPConnectionFactory imple // connection factory properties Properties cfProps = new Properties(); - cfProps.put("user", dbUser); - cfProps.put("password", dbPass); + cfProps.put("user", jdbcUsername); + cfProps.put("password", jdbcPassword); // create the connection factory - ConnectionFactory cf = new DriverConnectionFactory(jdbcDriver, dbUri, cfProps); + ConnectionFactory cf = new DriverConnectionFactory(jdbcDriver, jdbcUri, cfProps); // wrap it with a LocalXAConnectionFactory XAConnectionFactory xacf = new LocalXAConnectionFactory(txMgr, cf); @@ -156,9 +159,9 @@ public class DBCPConnectionFactory imple mds.setAccessToUnderlyingConnectionAllowed(true); // cache the pool - dsCache.put(helperName, mds); + dsCache.put(helperInfo.getHelperFullName(), mds); - return TransactionFactory.getCursorConnection(helperName, mds.getConnection()); + return TransactionFactory.getCursorConnection(helperInfo, mds.getConnection()); } } Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/MinervaConnectionFactory.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/MinervaConnectionFactory.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/MinervaConnectionFactory.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/connection/MinervaConnectionFactory.java Wed Mar 10 10:29:30 2010 @@ -30,6 +30,7 @@ import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilGenerics; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.datasource.GenericHelperInfo; import org.ofbiz.entity.transaction.TransactionFactory; import org.ofbiz.minerva.pool.jdbc.xa.XAPoolDataSource; import org.ofbiz.minerva.pool.jdbc.xa.wrapper.XADataSourceImpl; @@ -43,28 +44,33 @@ public class MinervaConnectionFactory im public static final String module = MinervaConnectionFactory.class.getName(); protected static Map<String, XAPoolDataSource> dsCache = FastMap.newInstance(); - public Connection getConnection(String helperName, Element jdbcElement) throws SQLException, GenericEntityException { - XAPoolDataSource pds = dsCache.get(helperName); + public Connection getConnection(GenericHelperInfo helperInfo, Element jdbcElement) throws SQLException, GenericEntityException { + XAPoolDataSource pds = dsCache.get(helperInfo.getHelperFullName()); if (pds != null) { - return TransactionFactory.getCursorConnection(helperName, pds.getConnection()); + return TransactionFactory.getCursorConnection(helperInfo, pds.getConnection()); } synchronized (MinervaConnectionFactory.class) { - pds = dsCache.get(helperName); + pds = dsCache.get(helperInfo.getHelperFullName()); if (pds != null) { return pds.getConnection(); } else { pds = new XAPoolDataSource(); - pds.setPoolName(helperName); + pds.setPoolName(helperInfo.getHelperFullName()); } XADataSourceImpl ds = new XADataSourceImpl(); - if (ds == null) + if (ds == null) { throw new GenericEntityException("XADataSource was not created, big problem!"); + } + + String jdbcUri = UtilValidate.isNotEmpty(helperInfo.getOverrideJdbcUri()) ? helperInfo.getOverrideJdbcUri() : jdbcElement.getAttribute("jdbc-uri"); + String jdbcUsername = UtilValidate.isNotEmpty(helperInfo.getOverrideUsername()) ? helperInfo.getOverrideUsername() : jdbcElement.getAttribute("jdbc-username"); + String jdbcPassword = UtilValidate.isNotEmpty(helperInfo.getOverridePassword()) ? helperInfo.getOverridePassword() : jdbcElement.getAttribute("jdbc-password"); ds.setDriver(jdbcElement.getAttribute("jdbc-driver")); - ds.setURL(jdbcElement.getAttribute("jdbc-uri")); + ds.setURL(jdbcUri); String transIso = jdbcElement.getAttribute("isolation-level"); if (UtilValidate.isNotEmpty(transIso)) { @@ -83,8 +89,8 @@ public class MinervaConnectionFactory im // set the datasource in the pool pds.setDataSource(ds); - pds.setJDBCUser(jdbcElement.getAttribute("jdbc-username")); - pds.setJDBCPassword(jdbcElement.getAttribute("jdbc-password")); + pds.setJDBCUser(jdbcUsername); + pds.setJDBCPassword(jdbcPassword); // set the transaction manager in the pool pds.setTransactionManager(TransactionFactory.getTransactionManager()); @@ -110,9 +116,9 @@ public class MinervaConnectionFactory im } // cache the pool - dsCache.put(helperName, pds); + dsCache.put(helperInfo.getHelperFullName(), pds); - return TransactionFactory.getCursorConnection(helperName, pds.getConnection()); + return TransactionFactory.getCursorConnection(helperInfo, pds.getConnection()); } } Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java Wed Mar 10 10:29:30 2010 @@ -71,24 +71,24 @@ public class GenericDAO { public static final String module = GenericDAO.class.getName(); private static final FastMap<String, GenericDAO> genericDAOs = FastMap.newInstance(); - private final String helperName; + private final GenericHelperInfo helperInfo; private final ModelFieldTypeReader modelFieldTypeReader; private final DatasourceInfo datasourceInfo; - public static GenericDAO getGenericDAO(String helperName) { - GenericDAO newGenericDAO = genericDAOs.get(helperName); + public static GenericDAO getGenericDAO(GenericHelperInfo helperInfo) { + GenericDAO newGenericDAO = genericDAOs.get(helperInfo.getHelperFullName()); if (newGenericDAO == null) { - genericDAOs.putIfAbsent(helperName, new GenericDAO(helperName)); - newGenericDAO = genericDAOs.get(helperName); + genericDAOs.putIfAbsent(helperInfo.getHelperFullName(), new GenericDAO(helperInfo)); + newGenericDAO = genericDAOs.get(helperInfo.getHelperFullName()); } return newGenericDAO; } - public GenericDAO(String helperName) { - this.helperName = helperName; - this.modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName); - this.datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperName); + public GenericDAO(GenericHelperInfo helperInfo) { + this.helperInfo = helperInfo; + this.modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperInfo.getHelperBaseName()); + this.datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperInfo.getHelperBaseName()); } private void addFieldIfMissing(List<ModelField> fieldsToSave, String fieldName, ModelEntity modelEntity) { @@ -108,7 +108,7 @@ public class GenericDAO { throw new GenericModelException("Could not find ModelEntity record for entityName: " + entity.getEntityName()); } - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); try { return singleInsert(entity, modelEntity, modelEntity.getFieldsUnmodifiable(), sqlP); @@ -209,7 +209,7 @@ public class GenericDAO { } private int customUpdate(GenericEntity entity, ModelEntity modelEntity, List<ModelField> fieldsToSave) throws GenericEntityException { - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); try { return singleUpdate(entity, modelEntity, fieldsToSave, sqlP); } catch (GenericEntityException e) { @@ -285,7 +285,7 @@ public class GenericDAO { } public int updateByCondition(ModelEntity modelEntity, Map<String, ? extends Object> fieldsToSet, EntityCondition condition) throws GenericEntityException { - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); try { return updateByCondition(modelEntity, fieldsToSet, condition, sqlP); @@ -482,7 +482,7 @@ public class GenericDAO { /* ====================================================================== */ public void select(GenericEntity entity) throws GenericEntityException { - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); try { select(entity, sqlP); @@ -582,7 +582,7 @@ public class GenericDAO { sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, datasourceInfo)); sqlBuffer.append(SqlJdbcUtil.makeWhereClause(modelEntity, modelEntity.getPkFieldsUnmodifiable(), entity, "AND", datasourceInfo.joinStyle)); - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); try { sqlP.prepareStatement(sqlBuffer.toString(), true, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); @@ -728,7 +728,7 @@ public class GenericDAO { // make the final SQL String String sql = sqlBuffer.toString(); - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); sqlP.prepareStatement(sql, findOptions.getSpecifyTypeAndConcur(), findOptions.getResultSetType(), findOptions.getResultSetConcurrency(), findOptions.getFetchSize(), findOptions.getMaxRows()); @@ -856,7 +856,7 @@ public class GenericDAO { public List<GenericValue> selectByMultiRelation(GenericValue value, ModelRelation modelRelationOne, ModelEntity modelEntityOne, ModelRelation modelRelationTwo, ModelEntity modelEntityTwo, List<String> orderBy) throws GenericEntityException { - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); // get the tables names String atable = modelEntityOne.getTableName(datasourceInfo); @@ -1077,7 +1077,7 @@ public class GenericDAO { String sql = sqlBuffer.toString(); if (Debug.verboseOn()) Debug.logVerbose("Count select sql: " + sql, module); - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); sqlP.prepareStatement(sql, findOptions.getSpecifyTypeAndConcur(), findOptions.getResultSetType(), findOptions.getResultSetConcurrency(), findOptions.getFetchSize(), findOptions.getMaxRows()); if (verboseOn) { @@ -1119,7 +1119,7 @@ public class GenericDAO { /* ====================================================================== */ public int delete(GenericEntity entity) throws GenericEntityException { - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); try { return delete(entity, sqlP); @@ -1156,7 +1156,7 @@ public class GenericDAO { } public int deleteByCondition(ModelEntity modelEntity, EntityCondition condition) throws GenericEntityException { - SQLProcessor sqlP = new SQLProcessor(helperName); + SQLProcessor sqlP = new SQLProcessor(helperInfo); try { return deleteByCondition(modelEntity, condition, sqlP); @@ -1194,13 +1194,13 @@ public class GenericDAO { /* ====================================================================== */ public void checkDb(Map<String, ModelEntity> modelEntities, List<String> messages, boolean addMissing) { - DatabaseUtil dbUtil = new DatabaseUtil(this.helperName); + DatabaseUtil dbUtil = new DatabaseUtil(this.helperInfo); 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.helperName); + DatabaseUtil dbUtil = new DatabaseUtil(this.helperInfo); return dbUtil.induceModelFromDb(messages); } } Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java Wed Mar 10 10:29:30 2010 @@ -43,15 +43,15 @@ public class GenericHelperDAO implements public static final String module = GenericHelperDAO.class.getName(); protected GenericDAO genericDAO; - protected String helperName; + protected GenericHelperInfo helperInfo; - public GenericHelperDAO(String helperName) { - this.helperName = helperName; - genericDAO = GenericDAO.getGenericDAO(helperName); + public GenericHelperDAO(GenericHelperInfo helperInfo) { + this.helperInfo = helperInfo; + genericDAO = GenericDAO.getGenericDAO(helperInfo); } public String getHelperName() { - return helperName; + return this.helperInfo.getHelperFullName(); } /** Creates a Entity in the form of a GenericValue and write it to the database Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperFactory.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperFactory.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperFactory.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperFactory.java Wed Mar 10 10:29:30 2010 @@ -37,20 +37,19 @@ public class GenericHelperFactory { // protected static UtilCache helperCache = new UtilCache("entity.GenericHelpers", 0, 0); protected static Map<String, GenericHelper> helperCache = new HashMap<String, GenericHelper>(); - public static GenericHelper getHelper(String helperName) { - GenericHelper helper = helperCache.get(helperName); + public static GenericHelper getHelper(GenericHelperInfo helperInfo) { + GenericHelper helper = helperCache.get(helperInfo.getHelperFullName()); - if (helper == null) // don't want to block here - { + if (helper == null) { // don't want to block here synchronized (GenericHelperFactory.class) { // must check if null again as one of the blocked threads can still enter - helper = helperCache.get(helperName); + helper = helperCache.get(helperInfo.getHelperFullName()); if (helper == null) { try { - DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperName); + DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperInfo.getHelperBaseName()); if (datasourceInfo == null) { - throw new IllegalStateException("Could not find datasource definition with name " + helperName); + throw new IllegalStateException("Could not find datasource definition with name " + helperInfo.getHelperBaseName()); } String helperClassName = datasourceInfo.helperClass; Class<?> helperClass = null; @@ -65,8 +64,8 @@ public class GenericHelperFactory { } } - Class<?>[] paramTypes = new Class<?>[] {String.class}; - Object[] params = new Object[] {helperName}; + Class<?>[] paramTypes = new Class<?>[] {GenericHelperInfo.class}; + Object[] params = new Object[] {helperInfo}; java.lang.reflect.Constructor<?> helperConstructor = null; @@ -92,7 +91,7 @@ public class GenericHelperFactory { } if (helper != null) - helperCache.put(helperName, helper); + helperCache.put(helperInfo.getHelperFullName(), helper); } catch (SecurityException e) { Debug.logError(e, module); throw new IllegalStateException("Error loading GenericHelper class: " + e.toString()); Added: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java?rev=921290&view=auto ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java (added) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java Wed Mar 10 10:29:30 2010 @@ -0,0 +1,91 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ + +package org.ofbiz.entity.datasource; + +import org.ofbiz.base.util.UtilValidate; + + + + +/** + * Generic Entity Helper Info Class + * + */ +public class GenericHelperInfo { + protected String entityGroupName; + protected String helperBaseName; + protected String tenantId = null; + protected String overrideJdbcUri = null; + protected String overrideUsername = null; + protected String overridePassword = null; + + public GenericHelperInfo(String entityGroupName, String helperBaseName) { + this.entityGroupName = entityGroupName; + this.helperBaseName = helperBaseName; + } + + public String getHelperFullName() { + if (UtilValidate.isNotEmpty(tenantId)) { + return helperBaseName + "#" + tenantId; + } else { + return helperBaseName; + } + } + + public String getEntityGroupName() { + return entityGroupName; + } + + public String getHelperBaseName() { + return helperBaseName; + } + + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + public String getOverrideJdbcUri() { + return overrideJdbcUri; + } + + public void setOverrideJdbcUri(String overrideJdbcUri) { + this.overrideJdbcUri = overrideJdbcUri; + } + + public String getOverrideUsername() { + return overrideUsername; + } + + public void setOverrideUsername(String overrideUsername) { + this.overrideUsername = overrideUsername; + } + + public String getOverridePassword() { + return overridePassword; + } + + public void setOverridePassword(String overridePassword) { + this.overridePassword = overridePassword; + } +} Propchange: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperInfo.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/jdbc/ConnectionFactory.java URL: http://svn.apache.org/viewvc/ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/jdbc/ConnectionFactory.java?rev=921290&r1=921289&r2=921290&view=diff ============================================================================== --- ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/jdbc/ConnectionFactory.java (original) +++ ofbiz/branches/multitenant20100310/framework/entity/src/org/ofbiz/entity/jdbc/ConnectionFactory.java Wed Mar 10 10:29:30 2010 @@ -23,6 +23,7 @@ import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.config.EntityConfigUtil; import org.ofbiz.entity.connection.ConnectionFactoryInterface; +import org.ofbiz.entity.datasource.GenericHelperInfo; import org.ofbiz.entity.transaction.TransactionFactory; import org.w3c.dom.Element; @@ -71,13 +72,23 @@ public class ConnectionFactory { public static Connection getConnection(String helperName) throws SQLException, GenericEntityException { // Debug.logVerbose("Getting a connection", module); - Connection con = TransactionFactory.getConnection(helperName); + Connection con = TransactionFactory.getConnection(new GenericHelperInfo(null, helperName)); if (con == null) { Debug.logError("******* ERROR: No database connection found for helperName \"" + helperName + "\"", module); } return con; } + public static Connection getConnection(GenericHelperInfo helperInfo) throws SQLException, GenericEntityException { + // Debug.logVerbose("Getting a connection", module); + + Connection con = TransactionFactory.getConnection(helperInfo); + if (con == null) { + Debug.logError("******* ERROR: No database connection found for helperName \"" + helperInfo.getHelperFullName() + "\"", module); + } + return con; + } + public static ConnectionFactoryInterface getManagedConnectionFactory() { if (_factory == null) { // don't want to block here synchronized (TransactionFactory.class) { @@ -120,8 +131,8 @@ public class ConnectionFactory { return _factory; } - public static Connection getManagedConnection(String helperName, Element inlineJdbcElement) throws SQLException, GenericEntityException { - return getManagedConnectionFactory().getConnection(helperName, inlineJdbcElement); + public static Connection getManagedConnection(GenericHelperInfo helperInfo, Element inlineJdbcElement) throws SQLException, GenericEntityException { + return getManagedConnectionFactory().getConnection(helperInfo, inlineJdbcElement); } public static void closeAllManagedConnections() { |
Free forum by Nabble | Edit this page |