diff --git a/org.adempiere.base/plugin.xml b/org.adempiere.base/plugin.xml
index 1f6d81fa85..eec5abfa71 100644
--- a/org.adempiere.base/plugin.xml
+++ b/org.adempiere.base/plugin.xml
@@ -9,5 +9,15 @@
+
+
+
+
+
diff --git a/org.adempiere.base/schema/org.adempiere.base.IModelFactory.exsd b/org.adempiere.base/schema/org.adempiere.base.IModelFactory.exsd
new file mode 100644
index 0000000000..c0a7e0e509
--- /dev/null
+++ b/org.adempiere.base/schema/org.adempiere.base.IModelFactory.exsd
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+ [Enter description of this extension point.]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [Enter the first release in which this extension point appears.]
+
+
+
+
+
+
+
+
+ [Enter extension point usage example here.]
+
+
+
+
+
+
+
+
+ [Enter API information here.]
+
+
+
+
+
+
+
+
+ [Enter information about supplied implementation of this extension point.]
+
+
+
+
+
diff --git a/org.adempiere.base/src/org/adempiere/base/DefaultModelFactory.java b/org.adempiere.base/src/org/adempiere/base/DefaultModelFactory.java
new file mode 100644
index 0000000000..c4c9a9fb05
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/DefaultModelFactory.java
@@ -0,0 +1,325 @@
+/******************************************************************************
+ * Product: Adempiere ERP & CRM Smart Business Solution *
+ * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms version 2 of the GNU General Public License as published *
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ * For the text or an alternative of this public license, you may reach us *
+ * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
+ * or via info@compiere.org or http://www.compiere.org/license.html *
+ * Contributor(s): Carlos Ruiz - globalqss *
+ *****************************************************************************/
+package org.adempiere.base;
+
+import java.lang.reflect.Constructor;
+import java.sql.ResultSet;
+import java.util.Properties;
+import java.util.logging.Level;
+
+import org.compiere.model.MEntityType;
+import org.compiere.model.MTable;
+import org.compiere.model.PO;
+import org.compiere.util.CCache;
+import org.compiere.util.CLogger;
+import org.compiere.util.Env;
+import org.compiere.util.Util;
+
+/**
+ * Default model factory implementation base on legacy code in MTable.
+ * @author Jorg Janke
+ * @author hengsin
+ */
+public class DefaultModelFactory implements IModelFactory {
+
+ private static CCache> s_classCache = new CCache>("PO_Class", 20);
+ private final static CLogger s_log = CLogger.getCLogger(DefaultModelFactory.class);
+
+ /** Packages for Model Classes */
+ private static final String[] s_packages = new String[] {
+
+ "org.compiere.model", "org.compiere.wf",
+ "org.compiere.print", "org.compiere.impexp",
+ "compiere.model", // globalqss allow compatibility with other plugins
+ "adempiere.model", // Extensions
+ "org.adempiere.model"
+ };
+
+ /** Special Classes */
+ private static final String[] s_special = new String[] {
+ "AD_Element", "org.compiere.model.M_Element",
+ "AD_Registration", "org.compiere.model.M_Registration",
+ "AD_Tree", "org.compiere.model.MTree_Base",
+ "R_Category", "org.compiere.model.MRequestCategory",
+ "GL_Category", "org.compiere.model.MGLCategory",
+ "K_Category", "org.compiere.model.MKCategory",
+ "C_ValidCombination", "org.compiere.model.MAccount",
+ "C_Phase", "org.compiere.model.MProjectTypePhase",
+ "C_Task", "org.compiere.model.MProjectTypeTask"
+ // AD_Attribute_Value, AD_TreeNode
+ };
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IModelFactory#getClass(java.lang.String)
+ */
+ @Override
+ public Class> getClass(String tableName) {
+// Not supported
+ if (tableName == null || tableName.endsWith("_Trl"))
+ return null;
+
+ //check cache
+ Class> cache = s_classCache.get(tableName);
+ if (cache != null)
+ {
+ //Object.class indicate no generated PO class for tableName
+ if (cache.equals(Object.class))
+ return null;
+ else
+ return cache;
+ }
+
+ MTable table = MTable.get(Env.getCtx(), tableName);
+ String entityType = table.getEntityType();
+
+ // Import Tables (Name conflict)
+ // Import Tables doesn't manage model M classes, just X_
+ if (tableName.startsWith("I_"))
+ {
+ MEntityType et = MEntityType.get(Env.getCtx(), entityType);
+ String etmodelpackage = et.getModelPackage();
+ if (etmodelpackage == null || MEntityType.ENTITYTYPE_Dictionary.equals(entityType))
+ etmodelpackage = "org.compiere.model"; // fallback for dictionary or empty model package on entity type
+ Class> clazz = getPOclass(etmodelpackage + ".X_" + tableName, tableName);
+ if (clazz != null)
+ {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+ s_log.warning("No class for table: " + tableName);
+ return null;
+ }
+
+ // Special Naming
+ for (int i = 0; i < s_special.length; i++)
+ {
+ if (s_special[i++].equals(tableName))
+ {
+ Class> clazz = getPOclass(s_special[i], tableName);
+ if (clazz != null)
+ {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+ break;
+ }
+ }
+
+ //begin [ 1784588 ] Use ModelPackage of EntityType to Find Model Class - vpj-cd
+ if (!MEntityType.ENTITYTYPE_Dictionary.equals(entityType))
+ {
+ MEntityType et = MEntityType.get(Env.getCtx(), entityType);
+ String etmodelpackage = et.getModelPackage();
+ if (etmodelpackage != null)
+ {
+ Class> clazz = null;
+ clazz = getPOclass(etmodelpackage + ".M" + Util.replace(tableName, "_", ""), tableName);
+ if (clazz != null) {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+ clazz = getPOclass(etmodelpackage + ".X_" + tableName, tableName);
+ if (clazz != null) {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+ s_log.warning("No class for table with it entity: " + tableName);
+ }
+ }
+ //end [ 1784588 ]
+
+ // Strip table name prefix (e.g. AD_) Customizations are 3/4
+ String className = tableName;
+ int index = className.indexOf('_');
+ if (index > 0)
+ {
+ if (index < 3) // AD_, A_
+ className = className.substring(index+1);
+ /* DELETEME: this part is useless - teo_sarca, [ 1648850 ]
+ else
+ {
+ String prefix = className.substring(0,index);
+ if (prefix.equals("Fact")) // keep custom prefix
+ className = className.substring(index+1);
+ }
+ */
+ }
+ // Remove underlines
+ className = Util.replace(className, "_", "");
+
+ // Search packages
+ for (int i = 0; i < s_packages.length; i++)
+ {
+ StringBuffer name = new StringBuffer(s_packages[i]).append(".M").append(className);
+ Class> clazz = getPOclass(name.toString(), tableName);
+ if (clazz != null)
+ {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+ }
+
+
+ // Adempiere Extension
+ Class> clazz = getPOclass("adempiere.model.X_" + tableName, tableName);
+ if (clazz != null)
+ {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+
+ //hengsin - allow compatibility with compiere plugins
+ //Compiere Extension
+ clazz = getPOclass("compiere.model.X_" + tableName, tableName);
+ if (clazz != null)
+ {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+
+ // Default
+ clazz = getPOclass("org.compiere.model.X_" + tableName, tableName);
+ if (clazz != null)
+ {
+ s_classCache.put(tableName, clazz);
+ return clazz;
+ }
+
+ //Object.class to indicate no PO class for tableName
+ s_classCache.put(tableName, Object.class);
+ return null;
+ }
+
+ /**
+ * Get PO class
+ * @param className fully qualified class name
+ * @param tableName Optional. If specified, the loaded class will be validated for that table name
+ * @return class or null
+ */
+ private Class> getPOclass (String className, String tableName)
+ {
+ try
+ {
+ Class> clazz = Class.forName(className);
+ // Validate if the class is for specified tableName
+ if (tableName != null)
+ {
+ String classTableName = clazz.getField("Table_Name").get(null).toString();
+ if (!tableName.equals(classTableName))
+ {
+ s_log.finest("Invalid class for table: " + className+" (tableName="+tableName+", classTableName="+classTableName+")");
+ return null;
+ }
+ }
+ // Make sure that it is a PO class
+ Class> superClazz = clazz.getSuperclass();
+ while (superClazz != null)
+ {
+ if (superClazz == PO.class)
+ {
+ s_log.fine("Use: " + className);
+ return clazz;
+ }
+ superClazz = superClazz.getSuperclass();
+ }
+ }
+ catch (Exception e)
+ {
+ }
+ s_log.finest("Not found: " + className);
+ return null;
+ } // getPOclass
+
+ @Override
+ public PO getPO(String tableName, int Record_ID, String trxName) {
+ Class> clazz = getClass(tableName);
+ if (clazz == null)
+ {
+ return null;
+ }
+
+ boolean errorLogged = false;
+ try
+ {
+ Constructor> constructor = null;
+ try
+ {
+ constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, int.class, String.class});
+ }
+ catch (Exception e)
+ {
+ String msg = e.getMessage();
+ if (msg == null)
+ msg = e.toString();
+ s_log.warning("No transaction Constructor for " + clazz + " (" + msg + ")");
+ }
+
+ PO po = (PO)constructor.newInstance(new Object[] {Env.getCtx(), new Integer(Record_ID), trxName});
+ return po;
+ }
+ catch (Exception e)
+ {
+ if (e.getCause() != null)
+ {
+ Throwable t = e.getCause();
+ s_log.log(Level.SEVERE, "(id) - Table=" + tableName + ",Class=" + clazz, t);
+ errorLogged = true;
+ if (t instanceof Exception)
+ s_log.saveError("Error", (Exception)e.getCause());
+ else
+ s_log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
+ }
+ else
+ {
+ s_log.log(Level.SEVERE, "(id) - Table=" + tableName + ",Class=" + clazz, e);
+ errorLogged = true;
+ s_log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
+ }
+ }
+ if (!errorLogged)
+ s_log.log(Level.SEVERE, "(id) - Not found - Table=" + tableName
+ + ", Record_ID=" + Record_ID);
+ return null;
+ }
+
+ @Override
+ public PO getPO(String tableName, ResultSet rs, String trxName) {
+ Class> clazz = getClass(tableName);
+ if (clazz == null)
+ {
+ return null;
+ }
+
+ boolean errorLogged = false;
+ try
+ {
+ Constructor> constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, ResultSet.class, String.class});
+ PO po = (PO)constructor.newInstance(new Object[] {Env.getCtx(), rs, trxName});
+ return po;
+ }
+ catch (Exception e)
+ {
+ s_log.log(Level.SEVERE, "(rs) - Table=" + tableName + ",Class=" + clazz, e);
+ errorLogged = true;
+ s_log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
+ }
+ if (!errorLogged)
+ s_log.log(Level.SEVERE, "(rs) - Not found - Table=" + tableName);
+ return null;
+ }
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/IModelFactory.java b/org.adempiere.base/src/org/adempiere/base/IModelFactory.java
new file mode 100644
index 0000000000..20e46c6386
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/IModelFactory.java
@@ -0,0 +1,49 @@
+/******************************************************************************
+ * Product: Adempiere ERP & CRM Smart Business Solution *
+ * Copyright (C) 2010 Heng Sin Low *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms version 2 of the GNU General Public License as published *
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ *****************************************************************************/
+package org.adempiere.base;
+
+import java.sql.ResultSet;
+
+import org.compiere.model.PO;
+
+/**
+ * Model factory interface, extracted from legacy code in MTable.
+ * @author hengsin
+ */
+public interface IModelFactory {
+ /**
+ * Get Persistence Class for Table
+ * @param tableName table name
+ * @return class or null
+ */
+ public Class> getClass (String tableName);
+
+ /**************************************************************************
+ * Get PO Class Instance
+ * @param tableName
+ * @param Record_ID record
+ * @param trxName
+ * @return PO for Record or null
+ */
+ public PO getPO (String tableName, int Record_ID, String trxName);
+
+ /**
+ * Get PO Class Instance
+ * @param tableName
+ * @param rs result set
+ * @param trxName transaction
+ * @return PO for Record or null
+ */
+ public PO getPO (String tableName, ResultSet rs, String trxName);
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/equinox/ExtensionPriorityManager.java b/org.adempiere.base/src/org/adempiere/base/equinox/ExtensionPriorityManager.java
new file mode 100644
index 0000000000..d53a67b9e2
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/equinox/ExtensionPriorityManager.java
@@ -0,0 +1,86 @@
+/******************************************************************************
+ * Product: Adempiere ERP & CRM Smart Business Solution *
+ * Copyright (C) 2010 Heng Sin Low *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms version 2 of the GNU General Public License as published *
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ *****************************************************************************/
+package org.adempiere.base.equinox;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.osgi.service.datalocation.Location;
+
+/**
+ *
+ * @author hengsin
+ *
+ */
+public class ExtensionPriorityManager {
+ private Properties priorityMap = new Properties();
+
+ private static final ExtensionPriorityManager instance = new ExtensionPriorityManager();
+
+ private ExtensionPriorityManager() {
+ Location location = Platform.getInstanceLocation();
+ URL url = location.getURL();
+ File file = new File(url.getPath(), "extensions-priorty.properties");
+ if (file.exists() && file.canRead()) {
+ try {
+ priorityMap.load(new FileInputStream(file));
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * @param element
+ * @return priority of extension
+ */
+ public int getPriority(IConfigurationElement element) {
+ int priority = 0;
+ String id = element.getDeclaringExtension().getUniqueIdentifier();
+ if (id != null) {
+ String p = priorityMap.getProperty(id);
+ if (p != null) {
+ try {
+ priority = Integer.parseInt(p);
+ return priority;
+ } catch (NumberFormatException e) {}
+ }
+ }
+ String p = element.getAttribute("priority");
+ if (p != null) {
+ try {
+ priority = Integer.parseInt(p);
+ return priority;
+ } catch (NumberFormatException e) {}
+ }
+ return priority;
+ }
+
+ /**
+ * @return ExtensionPriorityManager singleton instance
+ */
+ public static ExtensionPriorityManager getInstance() {
+ return instance;
+ }
+}
diff --git a/org.adempiere.base/src/org/compiere/model/MTable.java b/org.adempiere.base/src/org/compiere/model/MTable.java
index c44920ae6d..140a885f01 100644
--- a/org.adempiere.base/src/org/compiere/model/MTable.java
+++ b/org.adempiere.base/src/org/compiere/model/MTable.java
@@ -17,20 +17,20 @@
*****************************************************************************/
package org.compiere.model;
-import java.lang.reflect.Constructor;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
+import org.adempiere.base.IModelFactory;
+import org.adempiere.base.Service;
import org.adempiere.model.GenericPO;
import org.compiere.util.CCache;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
-import org.compiere.util.Env;
-import org.compiere.util.Util;
/**
* Persistent Table Model
@@ -52,12 +52,12 @@ public class MTable extends X_AD_Table
{
/**
- *
+ *
*/
private static final long serialVersionUID = -2367316254623142732L;
public final static int MAX_OFFICIAL_ID = 999999;
-
+
/**
* Get Table from Cache
* @param ctx context
@@ -92,9 +92,9 @@ public class MTable extends X_AD_Table
while (it.hasNext())
{
MTable retValue = it.next();
- if (tableName.equalsIgnoreCase(retValue.getTableName())
- && retValue.getCtx() == ctx
- )
+ if (tableName.equalsIgnoreCase(retValue.getTableName())
+ && retValue.getCtx() == ctx
+ )
{
return retValue;
}
@@ -128,7 +128,7 @@ public class MTable extends X_AD_Table
{
pstmt = null;
}
-
+
if (retValue != null)
{
Integer key = new Integer (retValue.getAD_Table_ID());
@@ -136,7 +136,7 @@ public class MTable extends X_AD_Table
}
return retValue;
} // get
-
+
/**
* Get Table Name
* @param ctx context
@@ -147,39 +147,16 @@ public class MTable extends X_AD_Table
{
return MTable.get(ctx, AD_Table_ID).getTableName();
} // getTableName
-
-
+
+
/** Cache */
private static CCache s_cache = new CCache("AD_Table", 20);
- private static CCache> s_classCache = new CCache>("PO_Class", 20);
-
+
/** Static Logger */
private static CLogger s_log = CLogger.getCLogger (MTable.class);
-
- /** Packages for Model Classes */
- private static final String[] s_packages = new String[] {
- "org.compiere.model", "org.compiere.wf",
- "org.compiere.print", "org.compiere.impexp",
- "compiere.model", // globalqss allow compatibility with other plugins
- "adempiere.model", // Extensions
- "org.adempiere.model"
- };
-
- /** Special Classes */
- private static final String[] s_special = new String[] {
- "AD_Element", "org.compiere.model.M_Element",
- "AD_Registration", "org.compiere.model.M_Registration",
- "AD_Tree", "org.compiere.model.MTree_Base",
- "R_Category", "org.compiere.model.MRequestCategory",
- "GL_Category", "org.compiere.model.MGLCategory",
- "K_Category", "org.compiere.model.MKCategory",
- "C_ValidCombination", "org.compiere.model.MAccount",
- "C_Phase", "org.compiere.model.MProjectTypePhase",
- "C_Task", "org.compiere.model.MProjectTypeTask"
- // AD_Attribute_Value, AD_TreeNode
- };
-
+
+
/**
* Get Persistence Class for Table
* @param tableName table name
@@ -187,194 +164,17 @@ public class MTable extends X_AD_Table
*/
public static Class> getClass (String tableName)
{
- // Not supported
- if (tableName == null || tableName.endsWith("_Trl"))
+ List factoryList = Service.list(IModelFactory.class);
+ if (factoryList == null)
return null;
-
- //check cache
- Class> cache = s_classCache.get(tableName);
- if (cache != null)
- {
- //Object.class indicate no generated PO class for tableName
- if (cache.equals(Object.class))
- return null;
- else
- return cache;
- }
-
- MTable table = MTable.get(Env.getCtx(), tableName);
- String entityType = table.getEntityType();
-
- // Import Tables (Name conflict)
- // Import Tables doesn't manage model M classes, just X_
- if (tableName.startsWith("I_"))
- {
- MEntityType et = MEntityType.get(Env.getCtx(), entityType);
- String etmodelpackage = et.getModelPackage();
- if (etmodelpackage == null || MEntityType.ENTITYTYPE_Dictionary.equals(entityType))
- etmodelpackage = "org.compiere.model"; // fallback for dictionary or empty model package on entity type
- Class> clazz = getPOclass(etmodelpackage + ".X_" + tableName, tableName);
+ for(IModelFactory factory : factoryList) {
+ Class> clazz = factory.getClass(tableName);
if (clazz != null)
- {
- s_classCache.put(tableName, clazz);
return clazz;
- }
- s_log.warning("No class for table: " + tableName);
- return null;
}
-
- // Special Naming
- for (int i = 0; i < s_special.length; i++)
- {
- if (s_special[i++].equals(tableName))
- {
- Class> clazz = getPOclass(s_special[i], tableName);
- if (clazz != null)
- {
- s_classCache.put(tableName, clazz);
- return clazz;
- }
- break;
- }
- }
-
- //begin [ 1784588 ] Use ModelPackage of EntityType to Find Model Class - vpj-cd
- if (!MEntityType.ENTITYTYPE_Dictionary.equals(entityType))
- {
- MEntityType et = MEntityType.get(Env.getCtx(), entityType);
- String etmodelpackage = et.getModelPackage();
- if (etmodelpackage != null)
- {
- Class> clazz = null;
- clazz = getPOclass(etmodelpackage + ".M" + Util.replace(tableName, "_", ""), tableName);
- if (clazz != null) {
- s_classCache.put(tableName, clazz);
- return clazz;
- }
- clazz = getPOclass(etmodelpackage + ".X_" + tableName, tableName);
- if (clazz != null) {
- s_classCache.put(tableName, clazz);
- return clazz;
- }
- s_log.warning("No class for table with it entity: " + tableName);
- }
- }
- //end [ 1784588 ]
-
- // Strip table name prefix (e.g. AD_) Customizations are 3/4
- String className = tableName;
- int index = className.indexOf('_');
- if (index > 0)
- {
- if (index < 3) // AD_, A_
- className = className.substring(index+1);
- /* DELETEME: this part is useless - teo_sarca, [ 1648850 ]
- else
- {
- String prefix = className.substring(0,index);
- if (prefix.equals("Fact")) // keep custom prefix
- className = className.substring(index+1);
- }
- */
- }
- // Remove underlines
- className = Util.replace(className, "_", "");
-
- // Search packages
- for (int i = 0; i < s_packages.length; i++)
- {
- StringBuffer name = new StringBuffer(s_packages[i]).append(".M").append(className);
- Class> clazz = getPOclass(name.toString(), tableName);
- if (clazz != null)
- {
- s_classCache.put(tableName, clazz);
- return clazz;
- }
- }
-
-
- // Adempiere Extension
- Class> clazz = getPOclass("adempiere.model.X_" + tableName, tableName);
- if (clazz != null)
- {
- s_classCache.put(tableName, clazz);
- return clazz;
- }
-
- //hengsin - allow compatibility with compiere plugins
- //Compiere Extension
- clazz = getPOclass("compiere.model.X_" + tableName, tableName);
- if (clazz != null)
- {
- s_classCache.put(tableName, clazz);
- return clazz;
- }
-
- // Default
- clazz = getPOclass("org.compiere.model.X_" + tableName, tableName);
- if (clazz != null)
- {
- s_classCache.put(tableName, clazz);
- return clazz;
- }
-
- //Object.class to indicate no PO class for tableName
- s_classCache.put(tableName, Object.class);
return null;
} // getClass
-
- /**
- * Get PO class
- * @param className fully qualified class name
- * @return class or null
- * @deprecated Use {@link #getPOclass(String, String)}
- */
- private static Class> getPOclass (String className)
- {
- return getPOclass(className, null);
- }
-
- /**
- * Get PO class
- * @param className fully qualified class name
- * @param tableName Optional. If specified, the loaded class will be validated for that table name
- * @return class or null
- */
- private static Class> getPOclass (String className, String tableName)
- {
- try
- {
- Class> clazz = Class.forName(className);
- // Validate if the class is for specified tableName
- if (tableName != null)
- {
- String classTableName = clazz.getField("Table_Name").get(null).toString();
- if (!tableName.equals(classTableName))
- {
- s_log.finest("Invalid class for table: " + className+" (tableName="+tableName+", classTableName="+classTableName+")");
- return null;
- }
- }
- // Make sure that it is a PO class
- Class> superClazz = clazz.getSuperclass();
- while (superClazz != null)
- {
- if (superClazz == PO.class)
- {
- s_log.fine("Use: " + className);
- return clazz;
- }
- superClazz = superClazz.getSuperclass();
- }
- }
- catch (Exception e)
- {
- }
- s_log.finest("Not found: " + className);
- return null;
- } // getPOclass
-
/**************************************************************************
* Standard Constructor
* @param ctx context
@@ -396,7 +196,7 @@ public class MTable extends X_AD_Table
setIsSecurityEnabled (false);
setIsView (false); // N
setReplicationType (REPLICATIONTYPE_Local);
- }
+ }
} // MTable
/**
@@ -409,10 +209,10 @@ public class MTable extends X_AD_Table
{
super(ctx, rs, trxName);
} // MTable
-
+
/** Columns */
private MColumn[] m_columns = null;
-
+
/**
* Get Columns
* @param requery requery
@@ -455,7 +255,7 @@ public class MTable extends X_AD_Table
list.toArray (m_columns);
return m_columns;
} // getColumns
-
+
/**
* Get Column
* @param columnName (case insensitive)
@@ -474,7 +274,7 @@ public class MTable extends X_AD_Table
}
return null;
} // getColumn
-
+
/**
* Table has a single Key
* @return true if table has single key column
@@ -484,7 +284,7 @@ public class MTable extends X_AD_Table
String[] keys = getKeyColumns();
return keys.length == 1;
} // isSingleKey
-
+
/**
* Get Key Columns of Table
* @return key columns
@@ -506,7 +306,7 @@ public class MTable extends X_AD_Table
retValue = list.toArray(retValue);
return retValue;
} // getKeyColumns
-
+
/**************************************************************************
* Get PO Class Instance
* @param Record_ID record
@@ -521,62 +321,34 @@ public class MTable extends X_AD_Table
log.log(Level.WARNING, "(id) - Multi-Key " + tableName);
return null;
}
- Class> clazz = getClass(tableName);
- if (clazz == null)
+
+ PO po = null;
+ List factoryList = Service.list(IModelFactory.class);
+ if (factoryList != null)
{
- //log.log(Level.WARNING, "(id) - Class not found for " + tableName);
- //return null;
- log.log(Level.INFO, "Using GenericPO for " + tableName);
- GenericPO po = new GenericPO(tableName, getCtx(), new Integer(Record_ID), trxName);
- return po;
- }
-
- boolean errorLogged = false;
- try
- {
- Constructor> constructor = null;
- try
+ for(IModelFactory factory : factoryList)
{
- constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, int.class, String.class});
- }
- catch (Exception e)
- {
- String msg = e.getMessage();
- if (msg == null)
- msg = e.toString();
- log.warning("No transaction Constructor for " + clazz + " (" + msg + ")");
- }
-
- PO po = (PO)constructor.newInstance(new Object[] {getCtx(), new Integer(Record_ID), trxName});
- if (po != null && po.get_ID() != Record_ID && Record_ID > 0)
- return null;
- return po;
- }
- catch (Exception e)
- {
- if (e.getCause() != null)
- {
- Throwable t = e.getCause();
- log.log(Level.SEVERE, "(id) - Table=" + tableName + ",Class=" + clazz, t);
- errorLogged = true;
- if (t instanceof Exception)
- log.saveError("Error", (Exception)e.getCause());
- else
- log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
- }
- else
- {
- log.log(Level.SEVERE, "(id) - Table=" + tableName + ",Class=" + clazz, e);
- errorLogged = true;
- log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
+ po = factory.getPO(tableName, Record_ID, trxName);
+ if (po != null)
+ {
+ if (po.get_ID() != Record_ID && Record_ID > 0)
+ po = null;
+ else
+ break;
+ }
}
}
- if (!errorLogged)
- log.log(Level.SEVERE, "(id) - Not found - Table=" + tableName
- + ", Record_ID=" + Record_ID);
- return null;
+
+ if (po == null)
+ {
+ po = new GenericPO(tableName, getCtx(), new Integer(Record_ID), trxName);
+ if (po.get_ID() != Record_ID && Record_ID > 0)
+ po = null;
+ }
+
+ return po;
} // getPO
-
+
/**
* Get PO Class Instance
* @param rs result set
@@ -586,32 +358,24 @@ public class MTable extends X_AD_Table
public PO getPO (ResultSet rs, String trxName)
{
String tableName = getTableName();
- Class> clazz = getClass(tableName);
- if (clazz == null)
+
+ PO po = null;
+ List factoryList = Service.list(IModelFactory.class);
+ if (factoryList != null)
{
- //log.log(Level.SEVERE, "(rs) - Class not found for " + tableName);
- //return null;
- log.log(Level.INFO, "Using GenericPO for " + tableName);
- GenericPO po = new GenericPO(tableName, getCtx(), rs, trxName);
- return po;
+ for(IModelFactory factory : factoryList) {
+ po = factory.getPO(tableName, rs, trxName);
+ if (po != null)
+ break;
+ }
}
-
- boolean errorLogged = false;
- try
+
+ if (po == null)
{
- Constructor> constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, ResultSet.class, String.class});
- PO po = (PO)constructor.newInstance(new Object[] {getCtx(), rs, trxName});
- return po;
+ po = new GenericPO(tableName, getCtx(), rs, trxName);
}
- catch (Exception e)
- {
- log.log(Level.SEVERE, "(rs) - Table=" + tableName + ",Class=" + clazz, e);
- errorLogged = true;
- log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
- }
- if (!errorLogged)
- log.log(Level.SEVERE, "(rs) - Not found - Table=" + tableName);
- return null;
+
+ return po;
} // getPO
/**
@@ -624,7 +388,7 @@ public class MTable extends X_AD_Table
{
return getPO(whereClause, null, trxName);
} // getPO
-
+
/**
* Get PO class instance
* @param whereClause
@@ -642,46 +406,38 @@ public class MTable extends X_AD_Table
if (info == null) return null;
StringBuffer sqlBuffer = info.buildSelect();
sqlBuffer.append(" WHERE ").append(whereClause);
- String sql = sqlBuffer.toString();
+ String sql = sqlBuffer.toString();
PreparedStatement pstmt = null;
+ ResultSet rs = null;
try
{
pstmt = DB.prepareStatement (sql, trxName);
- if (params != null && params.length > 0)
+ if (params != null && params.length > 0)
{
for (int i = 0; i < params.length; i++)
{
pstmt.setObject(i+1, params[i]);
}
}
- ResultSet rs = pstmt.executeQuery ();
+ rs = pstmt.executeQuery ();
if (rs.next ())
{
po = getPO(rs, trxName);
}
- rs.close ();
- pstmt.close ();
- pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
log.saveError("Error", e);
}
- try
+ finally
{
- if (pstmt != null)
- pstmt.close ();
- pstmt = null;
+ DB.close(rs, pstmt);
}
- catch (Exception e)
- {
- pstmt = null;
- }
-
+
return po;
}
-
+
/**
* Before Save
* @param newRecord new
@@ -694,7 +450,7 @@ public class MTable extends X_AD_Table
//
return true;
} // beforeSave
-
+
/**
* After Save
* @param newRecord new
@@ -720,11 +476,11 @@ public class MTable extends X_AD_Table
seq.setName(getTableName());
seq.save();
}
- }
-
+ }
+
return success;
} // afterSave
-
+
/**
* Get SQL Create
* @return create table DDL
@@ -759,7 +515,7 @@ public class MTable extends X_AD_Table
if (constraint != null && constraint.length() > 0)
constraints.append(", ").append(constraint);
}
- // Multi Column PK
+ // Multi Column PK
if (!hasPK && hasParents)
{
StringBuffer cols = new StringBuffer();
@@ -781,7 +537,7 @@ public class MTable extends X_AD_Table
.append(")");
return sb.toString();
} // getSQLCreate
-
+
// globalqss
/**
* Grant independence to GenerateModel from AD_Table_ID
@@ -808,14 +564,14 @@ public class MTable extends X_AD_Table
}
return retValue;
}
-
+
/**
* Create query to retrieve one or more PO.
* @param whereClause
* @param trxName
* @return Query
*/
- public Query createQuery(String whereClause, String trxName)
+ public Query createQuery(String whereClause, String trxName)
{
return new Query(this.getCtx(), this, whereClause, trxName);
}
@@ -830,5 +586,5 @@ public class MTable extends X_AD_Table
sb.append (get_ID()).append ("-").append (getTableName()).append ("]");
return sb.toString ();
} // toString
-
+
} // MTable
\ No newline at end of file
diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java
index 71fbe65723..afbc9b1448 100644
--- a/org.adempiere.base/src/org/compiere/model/PO.java
+++ b/org.adempiere.base/src/org/compiere/model/PO.java
@@ -116,9 +116,9 @@ public abstract class PO
private static DocWorkflowMgr s_docWFMgr = null;
/** User Maintained Entity Type */
- static protected final String ENTITYTYPE_UserMaintained = "U";
+ static public final String ENTITYTYPE_UserMaintained = "U";
/** Dictionary Maintained Entity Type */
- static protected final String ENTITYTYPE_Dictionary = "D";
+ static public final String ENTITYTYPE_Dictionary = "D";
/**************************************************************************
* Create New Persistent Object
diff --git a/org.adempiere.base/src/org/compiere/util/CLogFile.java b/org.adempiere.base/src/org/compiere/util/CLogFile.java
index 965b517a2b..f04e27609e 100644
--- a/org.adempiere.base/src/org/compiere/util/CLogFile.java
+++ b/org.adempiere.base/src/org/compiere/util/CLogFile.java
@@ -139,7 +139,7 @@ public class CLogFile extends Handler
{
fileName += File.separator;
if (isClient)
- fileName += "client";
+ fileName += "client.";
else
fileName += (CLogMgt.getRootLoggerName() +".");
m_fileNameDate = getFileNameDate(System.currentTimeMillis());
diff --git a/org.adempiere.server-feature/build.properties b/org.adempiere.server-feature/build.properties
index 791c39632b..34c18a2fe2 100644
--- a/org.adempiere.server-feature/build.properties
+++ b/org.adempiere.server-feature/build.properties
@@ -1,5 +1,5 @@
bin.includes = feature.xml
-root=file:build.xml,file:setup.ini
+root=file:build.xml,file:setup.ini,file:extensions-priorty.properties
root.folder.data=data
root.folder.setup=setup
#linux
diff --git a/org.adempiere.server-feature/extensions-priorty.properties b/org.adempiere.server-feature/extensions-priorty.properties
new file mode 100644
index 0000000000..05f41775e1
--- /dev/null
+++ b/org.adempiere.server-feature/extensions-priorty.properties
@@ -0,0 +1,2 @@
+#format is extension id=priority, for e.g com.foo.MyModelFactory=10
+#Higher priority value take precedence over lower value, system extensions have priority value 0