1. Added basic priority support for extensions. 2. Factor out the discovery of model class and instantiation of model po as extension.

This commit is contained in:
Heng Sin Low 2010-11-19 17:43:23 +08:00
parent bc72f1c6fe
commit 4709b790a6
10 changed files with 666 additions and 329 deletions

View File

@ -9,5 +9,15 @@
<extension-point id="org.compiere.db.AdempiereDatabase" name="Adempiere Database Interface" schema="schema/org.compiere.db.AdempiereDatabase.exsd"/> <extension-point id="org.compiere.db.AdempiereDatabase" name="Adempiere Database Interface" schema="schema/org.compiere.db.AdempiereDatabase.exsd"/>
<extension-point id="org.compiere.interfaces.Server" name="Server Interface" schema="schema/org.compiere.interfaces.Server.exsd"/> <extension-point id="org.compiere.interfaces.Server" name="Server Interface" schema="schema/org.compiere.interfaces.Server.exsd"/>
<extension-point id="org.compiere.interfaces.Status" name="Status interface" schema="schema/org.compiere.interfaces.Status.exsd"/> <extension-point id="org.compiere.interfaces.Status" name="Status interface" schema="schema/org.compiere.interfaces.Status.exsd"/>
<extension-point id="org.adempiere.base.IModelFactory" name="Model Factory" schema="schema/org.adempiere.base.IModelFactory.exsd"/>
<extension
id="org.adempiere.base.DefaultModelFactory"
name="Default model factory"
point="org.adempiere.base.IModelFactory">
<factory
class="org.adempiere.base.DefaultModelFactory"
priority="0">
</factory>
</extension>
</plugin> </plugin>

View File

@ -0,0 +1,109 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.adempiere.base" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="org.adempiere.base" id="org.adempiere.base.IModelFactory" name="Model Factory"/>
</appinfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<annotation>
<appinfo>
<meta.element />
</appinfo>
</annotation>
<complexType>
<choice>
<element ref="factory"/>
</choice>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="factory">
<complexType>
<attribute name="priority" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="class" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.adempiere.base.IModelFactory"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appinfo>
<meta.section type="since"/>
</appinfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="examples"/>
</appinfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="apiinfo"/>
</appinfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="implementation"/>
</appinfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>

View File

@ -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<String,Class<?>> s_classCache = new CCache<String,Class<?>>("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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -17,20 +17,20 @@
*****************************************************************************/ *****************************************************************************/
package org.compiere.model; package org.compiere.model;
import java.lang.reflect.Constructor;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.base.IModelFactory;
import org.adempiere.base.Service;
import org.adempiere.model.GenericPO; import org.adempiere.model.GenericPO;
import org.compiere.util.CCache; import org.compiere.util.CCache;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Util;
/** /**
* Persistent Table Model * Persistent Table Model
@ -52,12 +52,12 @@ public class MTable extends X_AD_Table
{ {
/** /**
* *
*/ */
private static final long serialVersionUID = -2367316254623142732L; private static final long serialVersionUID = -2367316254623142732L;
public final static int MAX_OFFICIAL_ID = 999999; public final static int MAX_OFFICIAL_ID = 999999;
/** /**
* Get Table from Cache * Get Table from Cache
* @param ctx context * @param ctx context
@ -92,9 +92,9 @@ public class MTable extends X_AD_Table
while (it.hasNext()) while (it.hasNext())
{ {
MTable retValue = it.next(); MTable retValue = it.next();
if (tableName.equalsIgnoreCase(retValue.getTableName()) if (tableName.equalsIgnoreCase(retValue.getTableName())
&& retValue.getCtx() == ctx && retValue.getCtx() == ctx
) )
{ {
return retValue; return retValue;
} }
@ -128,7 +128,7 @@ public class MTable extends X_AD_Table
{ {
pstmt = null; pstmt = null;
} }
if (retValue != null) if (retValue != null)
{ {
Integer key = new Integer (retValue.getAD_Table_ID()); Integer key = new Integer (retValue.getAD_Table_ID());
@ -136,7 +136,7 @@ public class MTable extends X_AD_Table
} }
return retValue; return retValue;
} // get } // get
/** /**
* Get Table Name * Get Table Name
* @param ctx context * @param ctx context
@ -147,39 +147,16 @@ public class MTable extends X_AD_Table
{ {
return MTable.get(ctx, AD_Table_ID).getTableName(); return MTable.get(ctx, AD_Table_ID).getTableName();
} // getTableName } // getTableName
/** Cache */ /** Cache */
private static CCache<Integer,MTable> s_cache = new CCache<Integer,MTable>("AD_Table", 20); private static CCache<Integer,MTable> s_cache = new CCache<Integer,MTable>("AD_Table", 20);
private static CCache<String,Class<?>> s_classCache = new CCache<String,Class<?>>("PO_Class", 20);
/** Static Logger */ /** Static Logger */
private static CLogger s_log = CLogger.getCLogger (MTable.class); 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 * Get Persistence Class for Table
* @param tableName table name * @param tableName table name
@ -187,194 +164,17 @@ public class MTable extends X_AD_Table
*/ */
public static Class<?> getClass (String tableName) public static Class<?> getClass (String tableName)
{ {
// Not supported List<IModelFactory> factoryList = Service.list(IModelFactory.class);
if (tableName == null || tableName.endsWith("_Trl")) if (factoryList == null)
return null; return null;
for(IModelFactory factory : factoryList) {
//check cache Class<?> clazz = factory.getClass(tableName);
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) if (clazz != null)
{
s_classCache.put(tableName, clazz);
return 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; return null;
} // getClass } // 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 * Standard Constructor
* @param ctx context * @param ctx context
@ -396,7 +196,7 @@ public class MTable extends X_AD_Table
setIsSecurityEnabled (false); setIsSecurityEnabled (false);
setIsView (false); // N setIsView (false); // N
setReplicationType (REPLICATIONTYPE_Local); setReplicationType (REPLICATIONTYPE_Local);
} }
} // MTable } // MTable
/** /**
@ -409,10 +209,10 @@ public class MTable extends X_AD_Table
{ {
super(ctx, rs, trxName); super(ctx, rs, trxName);
} // MTable } // MTable
/** Columns */ /** Columns */
private MColumn[] m_columns = null; private MColumn[] m_columns = null;
/** /**
* Get Columns * Get Columns
* @param requery requery * @param requery requery
@ -455,7 +255,7 @@ public class MTable extends X_AD_Table
list.toArray (m_columns); list.toArray (m_columns);
return m_columns; return m_columns;
} // getColumns } // getColumns
/** /**
* Get Column * Get Column
* @param columnName (case insensitive) * @param columnName (case insensitive)
@ -474,7 +274,7 @@ public class MTable extends X_AD_Table
} }
return null; return null;
} // getColumn } // getColumn
/** /**
* Table has a single Key * Table has a single Key
* @return true if table has single key column * @return true if table has single key column
@ -484,7 +284,7 @@ public class MTable extends X_AD_Table
String[] keys = getKeyColumns(); String[] keys = getKeyColumns();
return keys.length == 1; return keys.length == 1;
} // isSingleKey } // isSingleKey
/** /**
* Get Key Columns of Table * Get Key Columns of Table
* @return key columns * @return key columns
@ -506,7 +306,7 @@ public class MTable extends X_AD_Table
retValue = list.toArray(retValue); retValue = list.toArray(retValue);
return retValue; return retValue;
} // getKeyColumns } // getKeyColumns
/************************************************************************** /**************************************************************************
* Get PO Class Instance * Get PO Class Instance
* @param Record_ID record * @param Record_ID record
@ -521,62 +321,34 @@ public class MTable extends X_AD_Table
log.log(Level.WARNING, "(id) - Multi-Key " + tableName); log.log(Level.WARNING, "(id) - Multi-Key " + tableName);
return null; return null;
} }
Class<?> clazz = getClass(tableName);
if (clazz == null) PO po = null;
List<IModelFactory> factoryList = Service.list(IModelFactory.class);
if (factoryList != null)
{ {
//log.log(Level.WARNING, "(id) - Class not found for " + tableName); for(IModelFactory factory : factoryList)
//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
{ {
constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, int.class, String.class}); po = factory.getPO(tableName, Record_ID, trxName);
} if (po != null)
catch (Exception e) {
{ if (po.get_ID() != Record_ID && Record_ID > 0)
String msg = e.getMessage(); po = null;
if (msg == null) else
msg = e.toString(); break;
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);
} }
} }
if (!errorLogged)
log.log(Level.SEVERE, "(id) - Not found - Table=" + tableName if (po == null)
+ ", Record_ID=" + Record_ID); {
return 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 } // getPO
/** /**
* Get PO Class Instance * Get PO Class Instance
* @param rs result set * @param rs result set
@ -586,32 +358,24 @@ public class MTable extends X_AD_Table
public PO getPO (ResultSet rs, String trxName) public PO getPO (ResultSet rs, String trxName)
{ {
String tableName = getTableName(); String tableName = getTableName();
Class<?> clazz = getClass(tableName);
if (clazz == null) PO po = null;
List<IModelFactory> factoryList = Service.list(IModelFactory.class);
if (factoryList != null)
{ {
//log.log(Level.SEVERE, "(rs) - Class not found for " + tableName); for(IModelFactory factory : factoryList) {
//return null; po = factory.getPO(tableName, rs, trxName);
log.log(Level.INFO, "Using GenericPO for " + tableName); if (po != null)
GenericPO po = new GenericPO(tableName, getCtx(), rs, trxName); break;
return po; }
} }
boolean errorLogged = false; if (po == null)
try
{ {
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, ResultSet.class, String.class}); po = new GenericPO(tableName, getCtx(), rs, trxName);
PO po = (PO)constructor.newInstance(new Object[] {getCtx(), rs, trxName});
return po;
} }
catch (Exception e)
{ return po;
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;
} // getPO } // getPO
/** /**
@ -624,7 +388,7 @@ public class MTable extends X_AD_Table
{ {
return getPO(whereClause, null, trxName); return getPO(whereClause, null, trxName);
} // getPO } // getPO
/** /**
* Get PO class instance * Get PO class instance
* @param whereClause * @param whereClause
@ -642,46 +406,38 @@ public class MTable extends X_AD_Table
if (info == null) return null; if (info == null) return null;
StringBuffer sqlBuffer = info.buildSelect(); StringBuffer sqlBuffer = info.buildSelect();
sqlBuffer.append(" WHERE ").append(whereClause); sqlBuffer.append(" WHERE ").append(whereClause);
String sql = sqlBuffer.toString(); String sql = sqlBuffer.toString();
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null;
try try
{ {
pstmt = DB.prepareStatement (sql, trxName); 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++) for (int i = 0; i < params.length; i++)
{ {
pstmt.setObject(i+1, params[i]); pstmt.setObject(i+1, params[i]);
} }
} }
ResultSet rs = pstmt.executeQuery (); rs = pstmt.executeQuery ();
if (rs.next ()) if (rs.next ())
{ {
po = getPO(rs, trxName); po = getPO(rs, trxName);
} }
rs.close ();
pstmt.close ();
pstmt = null;
} }
catch (Exception e) catch (Exception e)
{ {
log.log(Level.SEVERE, sql, e); log.log(Level.SEVERE, sql, e);
log.saveError("Error", e); log.saveError("Error", e);
} }
try finally
{ {
if (pstmt != null) DB.close(rs, pstmt);
pstmt.close ();
pstmt = null;
} }
catch (Exception e)
{
pstmt = null;
}
return po; return po;
} }
/** /**
* Before Save * Before Save
* @param newRecord new * @param newRecord new
@ -694,7 +450,7 @@ public class MTable extends X_AD_Table
// //
return true; return true;
} // beforeSave } // beforeSave
/** /**
* After Save * After Save
* @param newRecord new * @param newRecord new
@ -720,11 +476,11 @@ public class MTable extends X_AD_Table
seq.setName(getTableName()); seq.setName(getTableName());
seq.save(); seq.save();
} }
} }
return success; return success;
} // afterSave } // afterSave
/** /**
* Get SQL Create * Get SQL Create
* @return create table DDL * @return create table DDL
@ -759,7 +515,7 @@ public class MTable extends X_AD_Table
if (constraint != null && constraint.length() > 0) if (constraint != null && constraint.length() > 0)
constraints.append(", ").append(constraint); constraints.append(", ").append(constraint);
} }
// Multi Column PK // Multi Column PK
if (!hasPK && hasParents) if (!hasPK && hasParents)
{ {
StringBuffer cols = new StringBuffer(); StringBuffer cols = new StringBuffer();
@ -781,7 +537,7 @@ public class MTable extends X_AD_Table
.append(")"); .append(")");
return sb.toString(); return sb.toString();
} // getSQLCreate } // getSQLCreate
// globalqss // globalqss
/** /**
* Grant independence to GenerateModel from AD_Table_ID * Grant independence to GenerateModel from AD_Table_ID
@ -808,14 +564,14 @@ public class MTable extends X_AD_Table
} }
return retValue; return retValue;
} }
/** /**
* Create query to retrieve one or more PO. * Create query to retrieve one or more PO.
* @param whereClause * @param whereClause
* @param trxName * @param trxName
* @return Query * @return Query
*/ */
public Query createQuery(String whereClause, String trxName) public Query createQuery(String whereClause, String trxName)
{ {
return new Query(this.getCtx(), this, whereClause, 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 ("]"); sb.append (get_ID()).append ("-").append (getTableName()).append ("]");
return sb.toString (); return sb.toString ();
} // toString } // toString
} // MTable } // MTable

View File

@ -116,9 +116,9 @@ public abstract class PO
private static DocWorkflowMgr s_docWFMgr = null; private static DocWorkflowMgr s_docWFMgr = null;
/** User Maintained Entity Type */ /** User Maintained Entity Type */
static protected final String ENTITYTYPE_UserMaintained = "U"; static public final String ENTITYTYPE_UserMaintained = "U";
/** Dictionary Maintained Entity Type */ /** Dictionary Maintained Entity Type */
static protected final String ENTITYTYPE_Dictionary = "D"; static public final String ENTITYTYPE_Dictionary = "D";
/************************************************************************** /**************************************************************************
* Create New Persistent Object * Create New Persistent Object

View File

@ -139,7 +139,7 @@ public class CLogFile extends Handler
{ {
fileName += File.separator; fileName += File.separator;
if (isClient) if (isClient)
fileName += "client"; fileName += "client.";
else else
fileName += (CLogMgt.getRootLoggerName() +"."); fileName += (CLogMgt.getRootLoggerName() +".");
m_fileNameDate = getFileNameDate(System.currentTimeMillis()); m_fileNameDate = getFileNameDate(System.currentTimeMillis());

View File

@ -1,5 +1,5 @@
bin.includes = feature.xml 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.data=data
root.folder.setup=setup root.folder.setup=setup
#linux #linux

View File

@ -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