From 4709b790a6c540ad279fe1e83f728716d4804aaf Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Fri, 19 Nov 2010 17:43:23 +0800 Subject: [PATCH] 1. Added basic priority support for extensions. 2. Factor out the discovery of model class and instantiation of model po as extension. --- org.adempiere.base/plugin.xml | 10 + .../org.adempiere.base.IModelFactory.exsd | 109 +++++ .../adempiere/base/DefaultModelFactory.java | 325 ++++++++++++++ .../src/org/adempiere/base/IModelFactory.java | 49 +++ .../equinox/ExtensionPriorityManager.java | 86 ++++ .../src/org/compiere/model/MTable.java | 406 ++++-------------- .../src/org/compiere/model/PO.java | 4 +- .../src/org/compiere/util/CLogFile.java | 2 +- org.adempiere.server-feature/build.properties | 2 +- .../extensions-priorty.properties | 2 + 10 files changed, 666 insertions(+), 329 deletions(-) create mode 100644 org.adempiere.base/schema/org.adempiere.base.IModelFactory.exsd create mode 100644 org.adempiere.base/src/org/adempiere/base/DefaultModelFactory.java create mode 100644 org.adempiere.base/src/org/adempiere/base/IModelFactory.java create mode 100644 org.adempiere.base/src/org/adempiere/base/equinox/ExtensionPriorityManager.java create mode 100644 org.adempiere.server-feature/extensions-priorty.properties 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