[cvs] expresso commit by yves: Yves Amaizo new changes commit today

JCorporate Ltd jcorp at jcorporate.com
Wed Aug 17 03:33:55 UTC 2005


Log Message:
-----------
Yves Amaizo new changes commit today 2005/08/17

Modified Files:
--------------
    expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/services/dbobj:
        DefaultUserInfo.java
    expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc:
        JDBCExecutor.java
        JDBCUtil.java
        JDBCDataObject.java
    expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/job:
        Job.java
    expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc:
        EMailSender.java
        ConfigContext.java
    expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core:
        expresso-config_4_0.dtd
    expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj:
        MultiDBObject.java
        DBObject.java
    expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db:
        DBConnection.java
        DBConnectionPool.java
        TableCreator.java

Revision Data
-------------
Index: DBObject.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/DBObject.java,v
retrieving revision 1.254
retrieving revision 1.255
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/DBObject.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/DBObject.java -u -r1.254 -r1.255
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/DBObject.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/DBObject.java
@@ -477,6 +477,47 @@
         notifyListeners(EVENT_ADD);
     } /* add() */
 
+	/**
+	 * Add records to the target table from the request ivoked inside DATABASE engine.
+	 * Assumes that the fields of this object are populated with data for the new
+	 * records. All key fields at least must be supplied with values, and all fields
+	 * that are specified as "no nulls". This method also validates all referential
+	 * integrity constraints specified by the object.
+	 *
+	 * @param valuesRequest  The string contains the select request to be executed. 
+	 *                       There is assumed to be a one to one or one to many relationship 
+	 *                       from this object to the specified object
+	 * 
+	 * @throws DBException If the record(s) cannot be added - this includes if the
+	 *                     record has a duplicate key
+	 *                     Added by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
+	 */
+	public void addAll(String valuesRequest, String fieldsToInput)
+			throws DBException {
+	
+		getExecutor().addAll(this, valuesRequest, fieldsToInput);
+	
+		/* Now log the change if we are logging */
+		if (getDef().isLoggingEnabled()) {
+			ChangeLog myChangeLog = new ChangeLog();
+			myChangeLog.setDataContext(getDataContext());
+			myChangeLog.setField("ObjectChanged", myClassName);
+			myChangeLog.setField("RecordKey", getMyKeys());
+			myChangeLog.setField("Operation", EVENT_ADD);
+			myChangeLog.setField("ChangedField", "ALL");
+			myChangeLog.add();
+	
+			/* We're done tracking changes */
+			myUpdates = null;
+		} /* if */
+	
+		// after add(), we know that 'current' values are now the baseline for comparison
+		setStatus(BaseDataObject.STATUS_CURRENT);
+		notifyListeners(EVENT_ADD);
+	} /* addAll(String) */
+
+
     /**
      * Hand a dbobject a connection that contains fields corresponding to
      * what the dbobject expects, and it'll set itself.
@@ -1339,6 +1380,8 @@
      * @param fieldName  Name of the field to verify
      * @param fieldValue Value of the field to be evaluated
      * @throws DBException If the value is not valid
+ 	 * Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
      */
     public synchronized void checkField(String fieldName, String fieldValue)
             throws DBException {
@@ -1456,9 +1499,17 @@
            null value.
             - Adam
         */
+		//
+		//
+		// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+		// @since $DatabaseSchema  $Date$
+		//  get SetupValues from mapped  SetupContext in DBObject 
+		//  important for application which use different database context for setupValues 
+		//
 
         // check for configuration (Setup) switch which turns off all relational integrity checking
-        String isCheckRelationalIntegrity = Setup.getValueUnrequired(getDataContext(), IS_CHECK_RELATIONAL_INTEGRITY);
+//        String isCheckRelationalIntegrity = Setup.getValueUnrequired(getDataContext(), IS_CHECK_RELATIONAL_INTEGRITY);
+		String isCheckRelationalIntegrity = Setup.getValueUnrequired(getSetupContext(), IS_CHECK_RELATIONAL_INTEGRITY);
         boolean isCheck = true; // default is true for legacy; this is only a switch used by a minority of developers
         if (isCheckRelationalIntegrity != null) {
             isCheck = StringUtil.toBoolean(isCheckRelationalIntegrity);
@@ -1530,6 +1581,8 @@
      * @param errorMessage    Error string to throw if the check fails
      * @param allowBlank      true if blank fields are allowed
      * @throws DBException If the referential integrity is not correct
+ 	 * Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
      */
     protected synchronized void checkRef(String foreignKeyNames,
                                          DBObject refObject,
@@ -1537,8 +1590,16 @@
                                          boolean allowBlank)
             throws DBException {
 
+				//
+				// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+				// @since $DatabaseSchema  $Date$
+				//  get SetupValues from mapped  SetupContext in DBObject 
+				//  important for application which use different database context for setupValues 
+				//
+
         // check for configuration (Setup) switch which turns off all relational integrity checking
-        String isCheckRelationalIntegrity = Setup.getValueUnrequired(getDataContext(), IS_CHECK_RELATIONAL_INTEGRITY);
+//		String isCheckRelationalIntegrity = Setup.getValueUnrequired(getDataContext(), IS_CHECK_RELATIONAL_INTEGRITY);
+        String isCheckRelationalIntegrity = Setup.getValueUnrequired(getSetupContext(), IS_CHECK_RELATIONAL_INTEGRITY);
         boolean isCheck = true; // default is true for legacy; this is only a switch used by a minority of developers
         if (isCheckRelationalIntegrity != null) {
             isCheck = StringUtil.toBoolean(isCheckRelationalIntegrity);
@@ -1834,7 +1895,7 @@
 
         FastStringBuffer sqlCommand = new FastStringBuffer(128);
         sqlCommand.append("DELETE FROM ");
-        sqlCommand.append(getJDBCMetaData().getTargetTable());
+        sqlCommand.append(getJDBCMetaData().getTargetSQLTable(getDataContext()));
 
         if (customWhereClause != null) {
             sqlCommand.append(customWhereClause);
@@ -2463,6 +2524,7 @@
      * Call inside find() to find if we have the keys needed to call retrieve()
      * instead of find which allows us to potentially use the Cache instead
      * of making a roundtrip to the database.
+     * @param metadata JDBCObjectMetaData the database metadata
      * @return boolean
      * @throws DBException
      */
@@ -5550,6 +5612,40 @@
         return recordSet;
     } /* searchAndRetrieveList() */
 
+	/**
+	 * Find a set of records of all of the objects that match the current
+	 * search critieria in the fields
+	 * and retrieve the list of all records that match this criteria
+	 * NOTE: Criteria in 'text' type colums is ignored (SQL Server limitation)
+	 * <p/>
+	 * SIDE-EFFECT: custom 'where' clause is set to null.
+	 *
+	 * @return DBConnection contains the return resultSet
+	 *         of the search
+	 * @throws DBException If the search could not be completed
+	 */
+	public synchronized DBConnection searchAndRetrieveList(String sqlSelectStatement, boolean customString) throws DBException {
+	
+	    DBConnection myConnection = null;
+	    try {
+	        myConnection = createAndExecuteSearch(sqlSelectStatement);
+	
+	    } catch (DBException de) {
+	        log.error("Error performing searchAndRetrieveList", de);
+	        throw new DBException(de);
+	    } catch (Throwable t) {
+	        log.error("Error performing searchAndRetrieveList", t);
+	        throw new DBException("Error performing searchAndRetrieveList", t);
+	    } finally {
+	        if (getLocalConnection() == null) {
+	            if (myConnection != null) {
+	                getConnectionPool().release(myConnection);
+	            }
+	        }
+	    }
+	    return myConnection;
+	} /* searchAndRetrieveList(String, boolean) */
+
 
     /**
      * Search and retrieve in a particular order
@@ -6846,6 +6942,8 @@
      * @throws DBException if the update to the database fails due to
      *                     a database error
      * @see #update(boolean)
+ 	 * Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
      */
     public void update()
             throws DBException {
@@ -6855,7 +6953,17 @@
         * 'blind updates' can set the Setup value UPDATE_CHANGED_ONLY to true
         * (a blind update is where the object is not retieved before values in it are reset)
         */
-        String onlychanged = Setup.getValueUnrequired(getDataContext(), UPDATE_CHANGED_ONLY);
+ 
+
+		//
+		// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+		// @since $DatabaseSchema  $Date$
+		//  get SetupValues from mapped  SetupContext in DBObject 
+		//  important for application which use different database context for setupValues 
+		//
+ 
+//		String onlychanged = Setup.getValueUnrequired(getDataContext(), UPDATE_CHANGED_ONLY);
+        String onlychanged = Setup.getValueUnrequired(getSetupContext(), UPDATE_CHANGED_ONLY);
         if (StringUtil.toBoolean(onlychanged)) {
             update(true);
         } else {
@@ -7585,6 +7693,52 @@
 
         return dbKey;
     }
+
+	/**
+	 * Returns the name of the currently set DataContext
+	 *
+	 * @return java.lang.String
+     * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+    *  @since $DatabaseSchema  $Date$
+	 */
+	public String getSetupContext() {
+	
+	    // set from RequestRegistry if this is first access
+	    if (setupKey == null || setupKey.length() == 0) {
+	        try {
+	            setSetupContext(RequestRegistry.getDataContext());
+	        } catch (Exception ex) {
+	            getLogger().warn("Problem getting data context from Registry: " +
+	                    ex.getClass().getName() + ", msg: " + ex.getMessage());
+				setSetupContext(DBConnection.DEFAULT_DB_CONTEXT_NAME);
+	        }
+	    }
+	
+	    return setupKey;
+	}
+
+	/**
+	 * Returns the name of the currently set DataContext
+	 *
+	 * @return java.lang.String
+	 * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	*  @since $DatabaseSchema  $Date$
+	 */
+	public String getCacheContext() {
+	
+	    // set from RequestRegistry if this is first access
+	    if (cacheKey == null || cacheKey.length() == 0) {
+	        try {
+	            setCacheContext(RequestRegistry.getDataContext());
+	        } catch (Exception ex) {
+	            getLogger().warn("Problem getting data context from Registry: " +
+	                    ex.getClass().getName() + ", msg: " + ex.getMessage());
+				setCacheContext(DBConnection.DEFAULT_DB_CONTEXT_NAME);
+	        }
+	    }
+	
+	    return cacheKey;
+	}
 
 
     /**
Index: MultiDBObject.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/MultiDBObject.java,v
retrieving revision 1.71
retrieving revision 1.72
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/MultiDBObject.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/MultiDBObject.java -u -r1.71 -r1.72
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/MultiDBObject.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dbobj/MultiDBObject.java
@@ -68,6 +68,7 @@
 import com.jcorporate.expresso.core.dataobjects.DataException;
 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData;
 import com.jcorporate.expresso.core.dataobjects.jdbc.FieldRangeParser;
+import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCUtil;
 import com.jcorporate.expresso.core.db.DBConnection;
 import com.jcorporate.expresso.core.db.DBConnectionPool;
 import com.jcorporate.expresso.core.db.DBException;
@@ -81,6 +82,8 @@
 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
 import org.apache.log4j.Logger;
 
+import java.io.InputStream;
+
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
@@ -1562,6 +1565,33 @@
         return recordSet;
     }
 
+	/**
+	 * Search and retrieve in a particular order
+	 *
+	 * @return DBConnection contains the return resultSet
+	 *         of the search
+	 * @throws DBException If the search could not be completed
+	 */
+	public synchronized DBConnection searchAndRetrieveList(String sqlSelectStatement, boolean customString) throws DBException {
+	    DBConnectionPool myPool = null;
+	    DBConnection myConnection = null;
+	
+	    try {
+	        if (localConnection != null) {
+	            myConnection = localConnection;
+	        } else {
+	            myPool = DBConnectionPool.getInstance(getDataContext());
+	            myConnection = myPool.getConnection("com.jcorporate.expresso.core.dbobj.DBObject");
+	        }
+			myConnection.execute(sqlSelectStatement);
+	    } finally {
+	        if (localConnection == null) {
+	            myConnection.release();
+	        }
+	    }
+	    return myConnection;
+	}
+
     /**
      * Retrieve rows found by statement param, and put retrieved strings into
      * DBObjects according to the mapping given in parameter, using prototype
@@ -1613,6 +1643,7 @@
 
 
             String oneFieldValue = null;
+			Object tmpData = null;
             int rowStringIndex = 1;
             for (Enumeration eachObj = myDBObjects.elements(); eachObj.hasMoreElements();) {
                 oneObj = (DBObject) eachObj.nextElement();
@@ -1628,7 +1659,43 @@
 
                     if (!metaData.isVirtual() && !metaData.isBinaryObjectType()) {
                         try {
-                            oneFieldValue = myConnection.getString(rowStringIndex);
+//                            oneFieldValue = myConnection.getString(rowStringIndex);
+                            
+							//   * @author	  Yves Henri AMAIZO
+							//   Handle correctly date from resultSet data retrieve from Database
+							//   17/05/2005 at 16:00 
+                            
+							if (metaData.isDateType()) {
+								tmpData = oneObj.getCustomStringFieldValue(myConnection, metaData.getName());
+							} else {
+								if (!metaData.isLongBinaryType() && !DBField.CLOB_TYPE.equals(metaData.getTypeString())) {
+									if (myConnection.isStringNotTrim()) {
+										tmpData = myConnection.getStringNoTrim(rowStringIndex);
+									} else {
+										tmpData = myConnection.getString(rowStringIndex);
+									}
+								} else {
+									if (metaData.isLongBinaryType()) {
+										tmpData = null;
+										InputStream is = myConnection.getBinaryStream(rowStringIndex);
+										if (is != null) {
+											byte[] bstr = new byte[JDBCUtil.LONGBINARY_READ_DEFAULT_SIZE];
+											int j = is.read(bstr);
+											if (j > 0) {
+												byte[] content = new byte[j];
+												System.arraycopy(bstr, 0, content, 0, j);
+												tmpData = content;
+											}
+										}
+									} else {
+										tmpData = myConnection.getStringNoTrim(rowStringIndex);
+									}
+
+								}
+							}
+                            
+                            
+                            
                         } catch (DBException de) {
                             String myName = (thisClass + "searchAndRetrieve()");
                             throw new DBException(myName +
@@ -1636,18 +1703,26 @@
                                     getTableName(oneObj) +
                                     "." + fieldName + "'",
                                     de);
-                        }
+                        } catch (Exception de1) {
+						throw new DataException("Not DBException(" + getClass().getName() +
+								") Error retrieving field '" +
+							metaData.getName() +
+								"' index " + rowStringIndex + ":" +
+								de1.getMessage(),
+								de1.getMessage());
+					}
 
                         rowStringIndex++;
 
                         if (log.isDebugEnabled()) {
                             log.debug("Setting " +
                                     getTableName(oneObj) + "." +
-                                    fieldName + " to " + oneFieldValue);
+                                    fieldName + " to " + tmpData.toString());
                         }
 
-                        myObj.setField((String) oneObj.getAttribute(SHORT_NAME),
-                                fieldName, oneFieldValue);
+//                        myObj.setField((String) oneObj.getAttribute(SHORT_NAME),
+//                                fieldName, oneFieldValue);
+						myObj.setField((String) oneObj.getAttribute(SHORT_NAME), fieldName, tmpData);
                     }
                 }
             } /* each db object */
@@ -1685,6 +1760,32 @@
         }
     }
 
+	/**
+	 * get the SQL select statment to be executed, if searchAnd RetrieveList happenned
+	 * on this MULTIDBOBJECT
+     * @param HashMap for the fields to retrieve per DBObject
+	 *
+	 * @return String of select statement to be executed
+	 * @throws DBException If the search could not be completed
+	 */
+	public synchronized String getSQLSelectStatement(HashMap rtrvListByTable) throws DBException {
+	    DBConnectionPool myPool = null;
+	    DBConnection myConnection = null;
+	    try {
+	        if (localConnection != null) {
+	            myConnection = localConnection;
+	        } else {
+	            myPool = DBConnectionPool.getInstance(getDataContext());
+	            myConnection = myPool.getConnection("com.jcorporate.expresso.core.dbobj.DBObject");
+	        }
+	        return getSQLSelectStatement(myPool, myConnection, rtrvListByTable);
+	    } finally {
+	        if (localConnection == null) {
+	            myPool.release(myConnection);
+	        }
+	    }
+	}
+
     /**
      * get the SQL select statment to be executed with a particular ORDER BY clause, if searchAnd RetrieveList happenned
      * on this MULTIDBOBJECT
@@ -2117,8 +2218,28 @@
 
         oneObj.setField(fieldName, fieldValue);
     }
+    
+	/**
+	 * Insert the method's description here.
+	 * <p/>
+	 * Creation date: (9/18/00 11:37:10 AM)
+	 *
+	 * @param shortName  the short name to set
+	 * @param fieldName  the fieldname to set
+	 * @param fieldValue the value to set the field at.
+	 */
+	public void setField(String shortName, String fieldName, Object fieldValue) throws
+			DBException {
+		DBObject oneObj = (DBObject) myDBObjects.get(shortName);
+
+		if (oneObj == null) {
+			String myName = thisClass + "setField(String, String, String)";
+			throw new DBException(myName + ":No such object as '" + shortName +
+					"'");
+		}
 
-    /* setField(String, String, String) */
+		oneObj.set(fieldName, fieldValue);
+	} /* setField(String, String, Object) */
 
     /**
      * Insert the method's description here.
Index: DefaultUserInfo.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/services/dbobj/DefaultUserInfo.java,v
retrieving revision 1.56
retrieving revision 1.57
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/services/dbobj/DefaultUserInfo.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/services/dbobj/DefaultUserInfo.java -u -r1.56 -r1.57
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/services/dbobj/DefaultUserInfo.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/services/dbobj/DefaultUserInfo.java
@@ -1374,6 +1374,8 @@
      * Check that another user with same email doesn't exist already
      *
      * @param isUpdate boolean for true = 'update' case (existing user, just changing email), false = 'add' case
+ 	 * Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
      */
     protected void checkEmailAddrAlreadyUsed(boolean isUpdate) throws DBException {
 
@@ -1387,8 +1389,17 @@
         }
 
         if (isUpdate) {
+ 
+			//
+			// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+			// @since $DatabaseSchema  $Date$
+			//  get SetupValues from mapped  SetupContext in DBObject 
+			//  important for application which use different database context for setupValues 
+			//
+
             // update case may be shortcircuited, thus requiring no db access
-            String onlychanged = Setup.getValueUnrequired(getDataContext(), UPDATE_CHANGED_ONLY);
+//			String onlychanged = Setup.getValueUnrequired(getDataContext(), UPDATE_CHANGED_ONLY);
+            String onlychanged = Setup.getValueUnrequired(getSetupContext(), UPDATE_CHANGED_ONLY);
             if (StringUtil.toBoolean(onlychanged)) {
                 // ok, setting says that this app only updates the field which are changed
                 // if email/login not changed, don't waste time checking for whether they are unique
Index: JDBCUtil.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCUtil.java,v
retrieving revision 1.34
retrieving revision 1.35
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCUtil.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCUtil.java -u -r1.34 -r1.35
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCUtil.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCUtil.java
@@ -86,7 +86,9 @@
 import java.text.SimpleDateFormat;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.Map;
+import java.text.NumberFormat;
 
 /**
  * This class provides utility functions that are common across the <code>jdbc.*</code>
@@ -105,6 +107,7 @@
     public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
     public static final String DATE_FORMAT = "yyyy-MM-dd";
     public static final String TIME_FORMAT = "HH:mm:ss";
+	public static int LONGBINARY_READ_DEFAULT_SIZE = 262144;
 
 
     private class DateReturnFormat {
@@ -710,6 +713,279 @@
         return myStatement;
     }
 
+	/**
+	 * Helper Function to build a prepared statement's SQL for an ADD statement.
+	 *
+     * @param criteria        the JDBCDataObject to build from
+     * 
+	 * @return a FastStringBuffer containing the build sql statement
+	 * @throws DBException upon error
+	 *                     <p/>
+	 *                     Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 */
+	public String buildSQLAddStatement(JDBCDataObject criteria) throws DBException {
+	    /**
+	     * sqlCommand will eventually = sqlCommand + valuesCommand.  The two
+	     * are assembled in parallel in the loop below.
+	     */
+	    FastStringBuffer sqlCommand = FastStringBuffer.getInstance();
+	    FastStringBuffer valuesCommand = FastStringBuffer.getInstance();
+	    String returnValue = null;
+	    try {
+	        sqlCommand.append("INSERT INTO ");
+	        sqlCommand.append(criteria.getJDBCMetaData().getTargetSQLTable(criteria.getDataContext()));
+	        sqlCommand.append(" (");
+	        valuesCommand.append(") VALUES (");
+	        DataFieldMetaData oneField = null;
+	        boolean needCommaValues = false;
+//			for (Iterator i = criteria.getFieldsToInputIterator(); i.hasNext();) {
+			for (Iterator i = criteria.getMetaData().getFieldNamesList().iterator(); i.hasNext();) {
+	            String oneFieldName = (String) i.next();
+	            oneField = criteria.getFieldMetaData(oneFieldName);
+	
+	            if (needCommaValues) {
+	               sqlCommand.append(", ");
+	               valuesCommand.append(", ");
+	            }
+	            sqlCommand.append(oneField.getName());
+	            valuesCommand.append(" ? ");
+	            needCommaValues = true;
+	        } /* for each field */
+	        //Now we merge the values of the parallel loops
+	        sqlCommand.append(valuesCommand);
+	        sqlCommand.append(")");
+	        returnValue = sqlCommand.toString();
+	    } finally {
+	        sqlCommand.release();
+	        valuesCommand.release();
+	        sqlCommand = null;
+	        valuesCommand = null;
+	    }
+	    return returnValue;
+	}
+
+	/**
+	 * Helper Function to build a prepared statement's SQL for an ADD statement.
+	 *
+	 * @param criteria        the JDBCDataObject to build from
+	 * @param fliedsName Formatted input fields list
+	 *                                only ones sent through the SQL query.
+	 * @param fliedsValues Formatted input fields values list without VALUES clause
+	 *                                only ones sent through the SQL query.
+	 * 
+	 * @return a FastStringBuffer containing the build sql statement
+	 * @throws DBException upon error
+	 *                     <p/>
+	 *                     Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 */
+	public String buildSQLAddStatement(JDBCDataObject criteria, String fliedsName, String fieldsValues) throws DBException {
+	    /**
+	     * sqlCommand will eventually = sqlCommand + valuesCommand.  The two
+	     * are assembled in parallel in the loop below.
+	     */
+	    FastStringBuffer sqlCommand = FastStringBuffer.getInstance();
+	    String returnValue = null;
+	    try {
+	        sqlCommand.append("INSERT INTO ");
+	        sqlCommand.append(criteria.getJDBCMetaData().getTargetSQLTable(criteria.getDataContext()));
+	        sqlCommand.append(" (");
+			sqlCommand.append(fliedsName);
+			sqlCommand.append(") VALUES (");
+			sqlCommand.append(fieldsValues);
+	        sqlCommand.append(")");
+	        returnValue = sqlCommand.toString();
+	    } finally {
+	        sqlCommand.release();
+	        sqlCommand = null;
+	    }
+	    return returnValue;
+	}
+
+	    /**
+	     * Helper function to build a prepared update statement for batch updates.
+	     *
+	     * @param criteria           A single <code>DataObject</code> that is used to model the prepared
+	     *                                statement.  Only metadata about the <code>JDBCDataObject</code>  is used.
+	     * @return A <code>FastStringBuffer</code> containing the proper SQL to create
+	     *         a preparedStatement
+	     * @throws DBException upon error
+	     *                     <p/>
+	     *                     Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	     */
+	public String buildSQLUpdateStatement(JDBCDataObject criteria) throws DBException {
+	
+	        FastStringBuffer sqlCommand = FastStringBuffer.getInstance();
+	        FastStringBuffer whereClause = FastStringBuffer.getInstance();
+	        String returnValue = null;
+	        try {
+	            sqlCommand.append("UPDATE ");
+	            sqlCommand.append(criteria.getJDBCMetaData().getTargetSQLTable(criteria.getDataContext()));
+	            sqlCommand.append(" SET ");
+	
+	            whereClause.append(" WHERE ");
+	
+	            DataFieldMetaData oneField = null;
+	            boolean needComma = false;
+	            boolean needWhereComma = false;
+	
+//				for (Iterator i = criteria.getFieldsToInputIterator(); i.hasNext();) {
+				for (Iterator i = criteria.getMetaData().getFieldNamesList().iterator(); i.hasNext();) {
+	                String oneFieldName = (String) i.next();
+	                oneField = criteria.getFieldMetaData(oneFieldName);
+	                /* We skip any key fields in the update part (not allowed to */
+	                /* upate them). Also skip any virtual fields */
+	                if ((!oneField.isKey()) && (!oneField.isVirtual()) &&
+	                        (!oneField.isAutoIncremented()) && (!oneField.isBinaryObjectType())) {
+	                    if (needComma) {
+	                        sqlCommand.append(", ");
+	                    }
+	                    sqlCommand.append(oneField.getName());
+	                    sqlCommand.append(" = ? ");
+	                    needComma = true;
+	                } else if (oneField.isKey()) {
+	                    if (needWhereComma) {
+	                        whereClause.append(" AND ");
+	                    }
+	                    whereClause.append(oneField.getName());
+	                    whereClause.append(" = ? ");
+	                    needWhereComma = true;
+	                }
+	
+	            }
+	            sqlCommand.append(whereClause);
+	            returnValue = sqlCommand.toString();
+	        } finally {
+	            whereClause.release();
+	            sqlCommand.release();
+	            whereClause = null;
+	            sqlCommand = null;
+	        }
+	        return returnValue;
+	    }
+
+		/**
+		 * Helper function to build a prepared update statement for batch updates.
+		 *
+		 * @param criteria           A single <code>DataObject</code> that is used to model the prepared
+		 *                                statement.  Only metadata about the <code>JDBCDataObject</code>  is used.
+		 * @param fliedsName Formatted input fields list
+		 *                                only ones sent through the SQL query.
+		 * @param whereCondition Formatted where conditions fields list without WHERE clause
+		 *                                only ones sent through the SQL query.
+		 * @return A <code>FastStringBuffer</code> containing the proper SQL to create
+		 *         a preparedStatement
+		 * @throws DBException upon error
+		 *                     <p/>
+		 *                     Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+		 */
+	public String buildSQLUpdateStatement(JDBCDataObject criteria, String fliedsName, String whereCondition) throws DBException {
+		
+		    FastStringBuffer sqlCommand = FastStringBuffer.getInstance();
+		    String returnValue = null;
+		    try {
+		        sqlCommand.append("UPDATE ");
+		        sqlCommand.append(criteria.getJDBCMetaData().getTargetSQLTable(criteria.getDataContext()));
+		        sqlCommand.append(" SET ");
+				sqlCommand.append(fliedsName);
+				sqlCommand.append(" WHERE ");
+				sqlCommand.append(whereCondition);
+		        returnValue = sqlCommand.toString();
+		    } finally {
+		        sqlCommand.release();
+		        sqlCommand = null;
+		    }
+		    return returnValue;
+		}
+
+		/**
+		 * Helper function to build a prepared delete statement for batch deletes.
+		 *
+		 * @param criteria A single <code>DataObject</code> that is used to model the prepared
+		 *                      statement.  Only metadata about the <code>DataObject</code>  is used.
+		 * @return A <code>FastStringBuffer</code> containing the proper SQL to create
+		 *         a preparedStatement
+		 * @throws DBException upon error
+		 *                     <p/>
+		 *                     Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+		 */
+	public String buildSQLDeleteStatement(JDBCDataObject criteria) throws DBException {
+		
+		    FastStringBuffer sqlCommand = FastStringBuffer.getInstance();
+		    FastStringBuffer whereClause = FastStringBuffer.getInstance();
+		    String returnValue = null;
+		    try {
+		        sqlCommand.append("DELETE FROM ");
+		        sqlCommand.append(criteria.getJDBCMetaData().getTargetSQLTable(criteria.getDataContext()));
+		
+		        whereClause.append(" WHERE ");
+		
+		        DataFieldMetaData oneField = null;
+		        boolean needComma = false;
+		        boolean needWhereComma = false;
+		
+		        for (Iterator i = criteria.getMetaData().getFieldNamesList().iterator(); i.hasNext();) {
+		            String oneFieldName = (String) i.next();
+		            oneField = criteria.getFieldMetaData(oneFieldName);
+		
+		            /* We skip any key fields in the update part (not allowed to */
+		            /* upate them). Also skip any virtual fields */
+		            if ((!oneField.isKey()) && (!oneField.isVirtual()) &&
+		                    (!oneField.isAutoIncremented()) && (!oneField.isBinaryObjectType())) {
+		            } else if (oneField.isKey()) {
+		                if (needWhereComma) {
+		                    whereClause.append(" AND ");
+		                }
+		
+		                whereClause.append(oneField.getName());
+		                whereClause.append(" = ? ");
+		                needWhereComma = true;
+		            }
+		
+		        }
+		
+		        sqlCommand.append(whereClause);
+		        returnValue = sqlCommand.toString();
+		    } finally {
+		        whereClause.release();
+		        sqlCommand.release();
+		        whereClause = null;
+		        sqlCommand = null;
+		    }
+		
+		    return returnValue;
+		}
+
+		/**
+		 * Helper function to build a prepared delete statement for batch deletes.
+		 *
+		 * @param criteria A single <code>DataObject</code> that is used to model the prepared
+		 *                      statement.  Only metadata about the <code>DataObject</code>  is used.
+		 * @param whereCondition Formatted where conditions fields list without WHERE clause
+		 *                                only ones sent through the SQL query.
+		 * @return A <code>FastStringBuffer</code> containing the proper SQL to create
+		 *         a preparedStatement
+		 * @throws DBException upon error
+		 *                     <p/>
+		 *                     Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+		 */
+	public String buildSQLDeleteStatement(JDBCDataObject criteria, String whereCondition) throws DBException {
+		
+		    FastStringBuffer sqlCommand = FastStringBuffer.getInstance();
+		    String returnValue = null;
+		    try {
+		        sqlCommand.append("DELETE FROM ");
+		        sqlCommand.append(criteria.getJDBCMetaData().getTargetSQLTable(criteria.getDataContext()));
+				sqlCommand.append(" WHERE ");
+		        sqlCommand.append(whereCondition);
+		        returnValue = sqlCommand.toString();
+		    } finally {
+		        sqlCommand.release();
+		        sqlCommand = null;
+		    }
+		
+		    return returnValue;
+		}
+
 
     /**
      * Creates the limitation syntax optimisation stub
@@ -1186,6 +1462,60 @@
             log.debug("Built callable statement for store procedure ");
         }
     } /* buildStoreProcedureCallableStatement(JDBCDataObject, boolean, CallableStatement) */
+    
+
+	/**
+	 * Helper function that get number formatter instance
+	 *
+	 * @return NumberFormat The number formatter instance
+	 * @throws DBException If there is no such field or it's value
+	 *                     cannot be converted to a float
+	 * @see #setField(String,double)
+	 */
+	public NumberFormat getNumberFormatter(JDBCDataObject criteria)
+			throws DBException {
+
+		Locale myLocale = Locale.getDefault();
+
+		try {
+			myLocale = new Locale(ConfigManager.getContext(criteria.getDataContext()).getLanguage(),
+					ConfigManager.getContext(criteria.getDataContext()).getCountry());
+		} catch (ConfigurationException ce) {
+			throw new DBException(ce);
+		}
+
+		NumberFormat formatter = NumberFormat.getInstance(myLocale);
+
+		return formatter;
+	} /* getNumberFormatter(JDBCDataObject) */
+
+	/**
+	 * Helper function that helps convert any string values from the database's
+	 * format
+	 *
+	 * @param theObject the source data object
+	 * @return SimpleDateFormat formatter instance
+	 * @throws DataException upon error (possibly conversion error)
+	 */
+	public SimpleDateFormat getDateFormatter(DataObject theObject) throws DataException {
+	
+	    String convertFormat = null;
+	    ConfigJdbc myConfig = null;
+	
+	    try {
+	            myConfig = ConfigManager.getJdbcRequired(theObject.getMappedDataContext());
+	    } catch (ConfigurationException ce) {
+	        throw new DataException(ce);
+	      }
+	      if (!StringUtil.notNull(myConfig.getDateSelectFormat()).equals("")) {
+	         convertFormat = myConfig.getDateSelectFormat();
+	      } else {
+	              convertFormat = DATETIME_FORMAT;
+	          }
+	    SimpleDateFormat formatter = getSimpleDateFormat(convertFormat);
+	
+	    return formatter;
+	}
 
 }
 
Index: JDBCExecutor.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCExecutor.java,v
retrieving revision 1.68
retrieving revision 1.69
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCExecutor.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCExecutor.java -u -r1.68 -r1.69
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCExecutor.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCExecutor.java
@@ -99,6 +99,7 @@
 import java.util.List;
 import java.util.Map;
 
+
 /**
  * Initial separation of DBObjects from the underlying JDBC code that gets executed.  This is
  * part number 1 where we move a lot of the JDBC code over to this helper class.  For round
@@ -520,37 +521,79 @@
                     } /* for each field */
 
                 } else { /* for each key field */
-                    for (Iterator i = metadata.getAllFieldsMap().values().iterator(); i.hasNext();) {
-                        oneField = (DBField) i.next();
-                        //We aren't retrieving long objects
-                        if (oneField.isBinaryObjectType()) {
-                            continue;
-                        }
-
-                        if (!oneField.isVirtual()) {
-                            if (needComma) {
-                                sqlCommand.append(", ");
-                            }
-
-                            sqlCommand.append(theObject.selectFieldString(oneField.getName()));
-                            needComma = true;
-                        } /* if field is not virtual */
-
-                        if (oneField.isVirtual()) {
-                            if (needComma) {
-                                sqlCommand.append(", ");
-                            }
-                            if (oneField.getTypeString().equalsIgnoreCase("varchar")) {
-                                sqlCommand.append(oneField.getDescription());
-                            }
-                            if (oneField.getTypeString().equalsIgnoreCase("int")) {
-                                sqlCommand.append(oneField.getDescription());
-                            }
-                            needComma = true;
-                        } /* if field is not virtual */
-
-                    } /* for */
+					if (theObject.getFieldsToInputCount() > 0) {
+						String oneFieldName = null;
+						Map inputFieldNames = new HashMap(10);
+
+
+
+						for (Iterator i = theObject.getFieldsToInputIterator(); i.hasNext();) {
+							oneFieldName = (String) i.next();
+							inputFieldNames.put(oneFieldName, null);
+
+							oneField = theObject.getMetaData().getFieldMetadata(oneFieldName);
+							if (oneField != null) {
+								if (!oneField.isVirtual()) {
+									if (needComma) {
+										sqlCommand.append(", ");
+									}
+									sqlCommand.append(theObject.selectFieldString(oneFieldName));
+								} else {
+									if (needComma) {
+										sqlCommand.append(", ");
+									}
+									if (oneField.getTypeString().equalsIgnoreCase("varchar")) {
+										sqlCommand.append("\'");
+										sqlCommand.append(oneField.getDescription());
+										sqlCommand.append("\'");
+									}
+									if (oneField.getTypeString().equalsIgnoreCase("int")) {
+										sqlCommand.append(oneField.getDescription());
+									}
+								  }
+								needComma = true;
+							} else {
+								if (needComma) {
+									sqlCommand.append(", ");
+								}
+								sqlCommand.append(oneFieldName);
+								needComma = true;
+							}
+						} /* for each field */
+
+					} else { /* for each key field */
+						for (Iterator i = metadata.getAllFieldsMap().values().iterator(); i.hasNext();) {
+							oneField = (DBField) i.next();
+							//We aren't retrieving long objects
+							if (oneField.isBinaryObjectType()) {
+								continue;
+							}
+
+
+							if (!oneField.isVirtual()) {
+								if (needComma) {
+									sqlCommand.append(", ");
+								}
+
+								sqlCommand.append(theObject.selectFieldString(oneField.getName()));
+								needComma = true;
+							} /* if field is not virtual */
+
+							if (oneField.isVirtual()) {
+								if (needComma) {
+									sqlCommand.append(", ");
+								}
+								if (oneField.getTypeString().equalsIgnoreCase("varchar")) {
+									sqlCommand.append(oneField.getDescription());
+								}
+								if (oneField.getTypeString().equalsIgnoreCase("int")) {
+									sqlCommand.append(oneField.getDescription());
+								}
+								needComma = true;
+							} /* if field is not virtual */
 
+						} /* for */
+					}
                 } /* if anyFieldsToInput */
 
                 //Now we merge the values of the parallel loops
@@ -1147,6 +1190,9 @@
      * @throws DataException         upon error communicating with the underlying data source
      * @throws DuplicateKeyException if one of the records was already in the
      *                               data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void addBatch(List valueObjectList) throws DataException, DuplicateKeyException {
         if (valueObjectList == null) {
@@ -1161,6 +1207,9 @@
      * @param valueObjectList A list of <code>DataObject</code>s to update to the underlying
      *                        data source
      * @throws DataException upon error updating the data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void updateBatch(List valueObjectList) throws DataException {
         if (valueObjectList == null) {
@@ -1532,6 +1581,9 @@
      *
      * @param valueObject the <code>DataObject</code> to delete.
      * @throws DataException upon error deleting the object to the data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void deleteAll(DataObject valueObject, boolean deleteChangedCache) throws DataException {
         if (valueObject == null) {
@@ -1745,6 +1797,9 @@
      * valueObject parameter.
      *
      * @param valueObject the DataObject who's keys are already set to retrieve
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void runStoreProcedure(DataObject valueObject)
             throws DataException {
@@ -1861,6 +1916,9 @@
      * @throws DataException         upon error communicating with the underlying data source
      * @throws DuplicateKeyException if one of the records was already in the
      *                               data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void addBatch(List valueObjectList, boolean addChangedFieldsOnly) throws DataException,
             DuplicateKeyException {
@@ -1996,17 +2054,8 @@
                 //We're done iterating through paramters/
 
                 int size = fieldData.size();
-//				try {
-//					prepStatement.clearParameters();
-//				} catch (NullPointerException ex) {
-//					//
-//					//Workaround for known Oracle bug. Clear parameters
-//					//throws NPE's
-//					//
-//					if (log.isDebugEnabled()) {
-//						log.debug("NPE.  Oracle Driver?", ex);
-//					}
-//				}
+
+
 
                 TypeMapper typeMapper = TypeMapper.getInstance(localConnection.getDataContext());
                 for (int j = 0; j < size; j++) {
@@ -2147,6 +2196,115 @@
         }
     }
 
+	/**
+	 * Adds an entire batch of <code>DataObject</code>s to the underlying JDBC data source
+	 *
+	 * @param valueObjectList      A list of <code>DataObject</code>s to add to the underlying
+	 *                             data source <b>NOTE:</b> you will get best performance if valueObjectList is
+	 *                             all one dataobject underneath.
+	 * @throws DataException         upon error communicating with the underlying data source
+	 * @throws DuplicateKeyException if one of the records was already in the
+	 *                               data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public void addBatch(DataObject valueObject) throws DataException,
+	        DuplicateKeyException {
+	    if (valueObject == null) {
+	        throw new IllegalArgumentException(myName + "addBatch(DataObject):  DataObject was null");
+	    }
+	
+	
+		DBObject theObject = (DBObject) valueObject;
+		DBConnectionPool myPool = null;
+	    DBConnection localConnection = null;
+	
+	    try {
+			localConnection = theObject.getLocalConnection();
+			if (localConnection == null) {
+				myPool = DBConnectionPool.getInstance(theObject.getMappedDataContext());
+				localConnection = myPool.getConnection("Batch Add PreparedStatement");
+			}
+			if (localConnection.supportsTransactions()) {
+				if (!localConnection.getImmortal()) {
+					localConnection.setAutoCommit(false);
+				}
+			}
+	
+			localConnection.getPreparedStatement().executeBatch();
+	        localConnection.clearPreparedStatement();
+	        if (!localConnection.getImmortal()) {
+	            localConnection.commit();
+	        }
+	    } catch (BatchUpdateException ex) {
+	        log.error("Batch Add PreparedStatement Exception", ex);
+	        try {
+	            if (!localConnection.getImmortal()) {
+	                localConnection.rollback();
+	            }
+	        } catch (DBException ex1) {
+	            log.error("Error rolling back transaction on local connection", ex1);
+	        }
+	        String msg = myName + "addBatch(DataObject) BatchUpdateException.  ";
+	        log.error(msg, ex);
+	        throw new DataException(msg, ex);
+	    } catch (java.lang.ClassCastException cce) {
+	        cce.printStackTrace();
+	        throw cce;
+	    } catch (NullPointerException npe) {
+	        npe.printStackTrace();
+	        throw npe;
+	    } catch (SQLException ex) {
+	        ex.printStackTrace();
+	        try {
+	            if (!localConnection.getImmortal()) {
+	                localConnection.rollback();
+	            }
+	        } catch (DBException ex1) {
+	            log.error("Error rolling back transaction on local connection", ex1);
+	        }
+	        String msg = myName + "addBatch(DataObject) SQLException.  ";
+	        log.error(msg, ex);
+	        throw new DataException(msg, ex);
+	    } catch (DBException ex) {
+	        try {
+	            if (!localConnection.getImmortal()) {
+	                localConnection.rollback();
+	            }
+	        } catch (DBException ex1) {
+	            log.error("Error rolling back transaction on local connection", ex1);
+	        }
+	        String msg = myName + "addBatch(DataObject) error";
+	        log.error(msg, ex);
+	        throw new DataException(msg, ex);
+	    } finally {
+	        if (localConnection.getPreparedStatement() != null) {
+	            try {
+	                if (!localConnection.getImmortal()) {
+						localConnection.getPreparedStatement().close();
+	                }
+	            } catch (SQLException ex) {
+	                log.error("Error closing prepared statement", ex);
+	            }
+	        }
+	
+	        if (localConnection != null) {
+	            localConnection.clearPreparedStatement();
+	        }
+	
+	        if (myPool != null) {
+	            if (localConnection != null) {
+	                //Auto-commit is automatically turned back on by
+	                //release
+	                if (!localConnection.getImmortal()) {
+	                    myPool.release(localConnection);
+	                }
+	            }
+	        }
+	    }
+	}
+
 
     /**
      * Updates an entire batch of <code>DataObject</code>s
@@ -2156,6 +2314,9 @@
      * @param updateChangedFieldsOnly flag to signify if only fields whose value
      *                                has changed should be included in the update.
      * @throws DataException upon error updating the data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void updateBatch(List valueObjectList, boolean updateChangedFieldsOnly) throws DataException {
         if (valueObjectList == null) {
@@ -2448,6 +2609,105 @@
         }
     }
 
+	    /**
+	     * Updates an entire batch of <code>DataObject</code>s
+	     *
+	     * @param valueObject         A list of <code>DataObject</code>s to update to the underlying
+	     *                                data source
+	     * @param updateChangedFieldsOnly flag to signify if only fields whose value
+	     *                                has changed should be included in the update.
+	     * @throws DataException upon error updating the data source
+		 *
+		 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 	 * @since Expresso 5.6
+	     */
+	    public void updateBatch(DataObject valueObject) throws DataException {
+	        if (valueObject == null) {
+	            throw new IllegalArgumentException(myName + "updateBatch(DataObjectn):  valueObject was null");
+	        }
+	
+			DBObject theObject = (DBObject) valueObject;
+			DBConnectionPool myPool = null;
+	        DBConnection localConnection = null;
+	        try {
+				localConnection = theObject.getLocalConnection();
+				if (localConnection == null) {
+					myPool = DBConnectionPool.getInstance(theObject.getMappedDataContext());
+					localConnection = myPool.getConnection("Batch Update PreparedStatement");
+				}
+				if (localConnection.supportsTransactions()) {
+					if (!localConnection.getImmortal()) {
+						localConnection.setAutoCommit(false);
+					}
+				}
+	
+				localConnection.getPreparedStatement().executeBatch();
+	            localConnection.clearPreparedStatement();
+	            if (!localConnection.getImmortal()) {
+	                localConnection.commit();
+	            }
+	        } catch (NullPointerException npe) {
+	            log.error("NPE Error performing batch update", npe);
+	            throw npe;
+	        } catch (NumberFormatException nfe) {
+	            log.error("NumberFormatException Error performing batch update", nfe);
+	            throw nfe;
+	        } catch (java.lang.ArrayIndexOutOfBoundsException ex) {
+	            log.error("ArrayIndexOutOfBoundsException performing batch update", ex);
+	            throw ex;
+	        } catch (ClassCastException cce) {
+	            log.error("Class Cast Exception performing batch update", cce);
+	            throw cce;
+	        } catch (SQLException ex) {
+	            try {
+	                if (!localConnection.getImmortal()) {
+	                    localConnection.rollback();
+	                }
+	            } catch (DBException ex1) {
+	                log.error("Error rolling back update batch transaction", ex1);
+	            }
+	            ex.printStackTrace();
+	            String msg = myName + "updateBatch(DataObject, updateChangedFieldsOnly) SQLException.  ";
+	            log.error(msg, ex);
+	            throw new DataException(msg, ex);
+	        } catch (DBException ex) {
+	            try {
+	                if (!localConnection.getImmortal()) {
+	                    localConnection.rollback();
+	                }
+	            } catch (DBException ex1) {
+	                log.error("Error rolling back update batch transaction", ex1);
+	            }
+	            String msg = myName + "updateBatch(DataObject, updateChangedFieldsOnly) error";
+	            log.error(msg, ex);
+	            throw new DataException(msg, ex);
+	        } catch (Throwable t) {
+	            log.error("Caught Throwable performing batch update", t);
+	            throw new DataException(t);
+	        } finally {
+	            if (localConnection.getPreparedStatement() != null) {
+	                try {
+						localConnection.getPreparedStatement().close();
+	                } catch (SQLException ex) {
+	                    log.error("Error closing prepared statement for batch update", ex);
+	                }
+	            }
+	            if (localConnection != null) {
+	                localConnection.clearPreparedStatement();
+	            }
+	
+	            if (myPool != null) {
+	                if (localConnection != null) {
+	                    //Auto-commit is automatically turned back on by
+	                    //release
+	                    if (!localConnection.getImmortal()) {
+	                        myPool.release(localConnection);
+	                    }
+	                }
+	            }
+	        }
+	    }
+
     /**
      * Updates an entire batch of <code>DataObject</code>s
      *
@@ -2455,6 +2715,9 @@
      *                                data source
      * @param deleteWithSetFieldsOnly Only include changed fields in the update
      * @throws DataException upon error updating the data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void deleteBatch(List valueObjectList, boolean deleteWithSetFieldsOnly) throws DataException {
         if (valueObjectList == null) {
@@ -2748,12 +3011,112 @@
 
     }
 
+	    /**
+	     * Updates an entire batch of <code>DataObject</code>s
+	     *
+	     * @param valueObject         A list of <code>DataObject</code>s to update to the underlying
+	     *                                data source
+	     * @throws DataException upon error updating the data source
+		 *
+		 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 	 * @since Expresso 5.6
+	     */
+	    public void deleteBatch(DataObject valueObject) throws DataException {
+	        if (valueObject == null) {
+	            throw new IllegalArgumentException(myName + "deleteBatch(DataObject):  valueObject was null");
+	        }
+	
+			DBObject theObject = (DBObject) valueObject;
+	        DBConnectionPool myPool = null;
+	        DBConnection localConnection = null;
+	        try {
+				localConnection = theObject.getLocalConnection();
+				if (localConnection == null) {
+					myPool = DBConnectionPool.getInstance(theObject.getMappedDataContext());
+					localConnection = myPool.getConnection("Batch Delete PreparedStatement");
+				}
+				if (localConnection.supportsTransactions()) {
+					if (!localConnection.getImmortal()) {
+						localConnection.setAutoCommit(false);
+					}
+				}
+				localConnection.getPreparedStatement().executeBatch();
+	            localConnection.clearPreparedStatement();
+	            if (!localConnection.getImmortal()) {
+	                localConnection.commit();
+	            }
+	        } catch (NullPointerException npe) {
+	            log.error("NPE Error performing batch delete", npe);
+	            throw npe;
+	        } catch (NumberFormatException nfe) {
+	            log.error("NumberFormatException Error performing batch delete", nfe);
+	            throw nfe;
+	        } catch (java.lang.ArrayIndexOutOfBoundsException ex) {
+	            log.error("ArrayIndexOutOfBoundsException performing batch delete", ex);
+	            throw ex;
+	        } catch (ClassCastException cce) {
+	            log.error("Class Cast Exception performing batch delete", cce);
+	            throw cce;
+	        } catch (SQLException ex) {
+	            try {
+	                if (!localConnection.getImmortal()) {
+	                    localConnection.rollback();
+	                }
+	            } catch (DBException ex1) {
+	                log.error("Error rolling back delete batch transaction", ex1);
+	            }
+	            ex.printStackTrace();
+	            String msg = myName + "deleteBatch(DataObject) SQLException.  ";
+	            log.error(msg, ex);
+	            throw new DataException(msg, ex);
+	        } catch (DBException ex) {
+	            try {
+	                if (!localConnection.getImmortal()) {
+	                    localConnection.rollback();
+	                }
+	            } catch (DBException ex1) {
+	                log.error("Error rolling back delete batch transaction", ex1);
+	            }
+	            String msg = myName + "deleteBatch(DataObject) error";
+	            log.error(msg, ex);
+	            throw new DataException(msg, ex);
+	        } catch (Throwable t) {
+	            log.error("Caught Throwable performing batch delete", t);
+	            throw new DataException(t);
+	        } finally {
+	            if (localConnection.getPreparedStatement() != null) {
+	                try {
+						localConnection.getPreparedStatement().close();
+	                } catch (SQLException ex) {
+	                    log.error("Error closing prepared statement for batch delete", ex);
+	                }
+	            }
+	            if (localConnection != null) {
+	                localConnection.clearPreparedStatement();
+	            }
+	
+	            if (myPool != null) {
+	                if (localConnection != null) {
+	                    //Auto-commit is automatically turned back on by
+	                    //release
+	                    if (!localConnection.getImmortal()) {
+	                        myPool.release(localConnection);
+	                    }
+	                }
+	            }
+	        }
+	
+	    }
+
     /**
      * Deletes an entire batch of <code>DataObject</code>s
      *
      * @param valueObjectList A list of <code>DataObject</code>s to delete to the underlying
      *                        data source
      * @throws DataException upon error deleting the data source
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
      */
     public void deleteBatch(List valueObjectList) throws DataException {
         if (valueObjectList == null) {
Index: JDBCDataObject.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCDataObject.java,v
retrieving revision 1.48
retrieving revision 1.49
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCDataObject.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCDataObject.java -u -r1.48 -r1.49
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCDataObject.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/dataobjects/jdbc/JDBCDataObject.java
@@ -81,6 +81,7 @@
 import com.jcorporate.expresso.core.misc.ConfigManager;
 import com.jcorporate.expresso.core.misc.ConfigurationException;
 import com.jcorporate.expresso.core.misc.DateTime;
+import com.jcorporate.expresso.core.misc.DateTimeForThread;
 import com.jcorporate.expresso.core.misc.StringUtil;
 import com.jcorporate.expresso.core.registry.RequestRegistry;
 import com.jcorporate.expresso.core.security.CryptoManager;
@@ -142,6 +143,20 @@
      */
     protected String dbKey = null;
 
+	/**
+	 * setupKey is used to indicate that the setup table database context name
+	 * other than the default database. Null indicates it's in the default
+	 * database
+	 */
+	protected String setupKey = null;
+
+	/**
+	 * cacheKey is used to indicate that the cache tables database context name
+	 * other than the default database. Null indicates it's in the default
+	 * database
+	 */
+	protected String cacheKey = null;
+
 
     /**
      * The ArrayList of DB objects retrieved by the last searchAndRetrieve method
@@ -408,8 +423,33 @@
             log.debug("Object '" + myClassName + "' requesting db '" +
                     newOther + "'");
         }
+		//
+		//
+		// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+		// @since $DatabaseSchema  $Date$
+		//  store mapped SetupValuesContext, CacheContext in DBObject 
+		//  important for application which use different database context for setupValues and cacheDBObject 
+		//
+        
         String mappedContext = newOther;
+		String setupContextName = "";
+		String cacheContextName = "";
         dbKey = newOther;
+        try {
+			setupContextName = StringUtil.notNull(ConfigManager.getContext(newOther).getSetupContext());
+			if ("".equals(setupContextName)) {
+				setupContextName = dbKey;
+			}
+			cacheContextName = StringUtil.notNull(ConfigManager.getContext(newOther).getCacheContext());
+			if ("".equals(cacheContextName)) {
+				cacheContextName = dbKey;
+			}
+        } catch(ConfigurationException ce) {
+        	throw new DBException(ce);
+        }
+        setSetupContext(setupContextName);
+		setCacheContext(cacheContextName);
+		
         /* We don't allow an alternate database name to be specified for DBOtherMap itself! */
         if (!"com.jcorporate.expresso.services.dbobj.DBOtherMap".equals(myClassName)) {
             String otherdbname = StringUtil.notNull(ConfigManager.getOtherDbLocation(newOther, myClassName));
@@ -501,6 +541,24 @@
         mappedDataContext = newMappedName;
     }
 
+
+	/**
+	 * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	*  @since $DatabaseSchema  $Date$
+	*/
+	protected void setCacheContext(String newCacheName) {
+	    mappedDataContext = newCacheName;
+	}
+
+
+	/**
+	 * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	*  @since $DatabaseSchema  $Date$
+	*/
+	protected void setSetupContext(String newSetupName) {
+	    setupKey = newSetupName;
+	}
+
     /**
      * This tells the buildWhereClause to either respect case (true) or
      * ignore case (false). You can call this method before doing a search and
@@ -797,6 +855,110 @@
         }
     }
 
+	/**
+	 * Refactoring to split the execution of a query statement into the query
+	 * part and the load part.  The DBConnection returned will have the query
+	 * already executed.
+	 * <p/>
+	 * SIDE-EFFECT: custom 'where' clause is set to null.
+	 *
+	 * @param sqlSelectStatement SQL statement to beexecuted on the connection
+	 *             
+	 * @return connection that has already executed the search statement.
+	 *         <p/>
+	 *         Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @throws DBException upon database communication error
+	
+	 */
+	public DBConnection createAndExecuteSearch(String sqlSelectStatement)
+	        throws DBException {
+	
+	    if (recordSet == null) {
+	        recordSet = new ArrayList();
+	    } else {
+	        recordSet.clear();
+	    }
+	
+	    myUpdates = null;
+	
+	    DBConnection myConnection = null;
+	    try {
+	      if (localConnection != null) {
+	        myConnection = localConnection;
+	      }
+	      else {
+	        myConnection = this.getConnectionPool().getConnection(this.myClassName);
+	      }
+	
+	      myConnection.execute(sqlSelectStatement);
+	      return myConnection;
+	    } catch (DBException ex) {
+	        if (myConnection != null && localConnection == null) {
+	            myConnection.release();
+	        }
+	        log.error("Error building and executing search statement", ex);
+	        throw ex;
+	    }
+	}
+
+	/**
+	 * Refactoring to split the execution of a query statement into the query
+	 * part and the load part.  The DBConnection returned will have the query
+	 * already executed.
+	 * <p/>
+	 * SIDE-EFFECT: custom 'where' clause is set to null.
+	 *
+	 * @param retrievedFieldList instantiate an ArrayList and the function will
+	 *                           fill out the field order that the SQL statement will have it's fields in.
+	 * @return connection that has already executed the search statement.
+	 *         <p/>
+	 *         Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @throws DBException upon database communication error
+	
+	 */
+	public void createPreparedStatement() throws DBException {
+	 
+	 	String sqlStatement = sJdbcUtil.buildSQLAddStatement(this);      
+		createPreparedStatement(sqlStatement);
+	}
+
+	/**
+	 * Refactoring to split the execution of a query statement into the query
+	 * part and the load part.  The DBConnection returned will have the query
+	 * already executed.
+	 * <p/>
+	 * SIDE-EFFECT: custom 'where' clause is set to null.
+	 *
+	 * @param retrievedFieldList instantiate an ArrayList and the function will
+	 *                           fill out the field order that the SQL statement will have it's fields in.
+	 * @return connection that has already executed the search statement.
+	 *         <p/>
+	 *         Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @throws DBException upon database communication error
+	
+	 */
+	public void createPreparedStatement(String sqlStatement)
+	        throws DBException {
+	
+	    DBConnection myConnection = null;
+	    try {
+	      if (localConnection != null) {
+	        myConnection = localConnection;
+	      }
+	      else {
+	        myConnection = this.getConnectionPool().getConnection(this.myClassName);
+	      }
+	
+	      myConnection.createPreparedStatement(sqlStatement);
+	    } catch (DBException ex) {
+	        if (myConnection != null && localConnection == null) {
+	            myConnection.release();
+	        }
+	        log.error("Error building and create prepared statement", ex);
+	        throw ex;
+	    }
+	}
+
     /**
     * Create the SQL select statement to be executed if the if searchAndRetrieveList is
     * invoked
@@ -1289,6 +1451,7 @@
             throws DBException {
         ConfigJdbc myConfig = null;
         String oneFieldValue = null;
+        DateTimeForThread dateInstance = DateTimeForThread.getInstance(dbKey);
         DataFieldMetaData fieldMetadata = this.getFieldMetaData(oneFieldName);
         try {
             myConfig = ConfigManager.getJdbcRequired(getDataContext());
@@ -1297,21 +1460,21 @@
         }
         if (fieldMetadata.isDateTimeType()) {
             if (StringUtil.notNull(myConfig.getDateTimeSelectFormat()).length() > 0) {
-                oneFieldValue = DateTime.getDateTimeForDB(connection.getTimestamp(oneFieldName), dbKey);
+                oneFieldValue = dateInstance.getDateTimeForDB(connection.getTimestamp(oneFieldName), dbKey);
             } else {
                 oneFieldValue = connection.getString(oneFieldName);
             }
         }
         if (fieldMetadata.isTimeType()) {
             if (!StringUtil.notNull(myConfig.getTimeSelectFormat()).equals("")) {
-                oneFieldValue = DateTime.getTimeForDB(connection.getTime(oneFieldName), dbKey);
+                oneFieldValue = dateInstance.getTimeForDB(connection.getTime(oneFieldName), dbKey);
             } else {
                 oneFieldValue = connection.getString(oneFieldName);
             }
         }
         if (fieldMetadata.isDateOnlyType()) {
             if (!StringUtil.notNull(myConfig.getDateSelectFormat()).equals("")) {
-                oneFieldValue = DateTime.getDateForDB(connection.getDate(oneFieldName), dbKey);
+                oneFieldValue = dateInstance.getDateForDB(connection.getDate(oneFieldName), dbKey);
             } else {
                 oneFieldValue = connection.getString(oneFieldName);
             }
Index: Job.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/job/Job.java,v
retrieving revision 1.39
retrieving revision 1.40
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/job/Job.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/job/Job.java -u -r1.39 -r1.40
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/job/Job.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/job/Job.java
@@ -278,6 +278,8 @@
      *
      * @param msg the message to send to the queuing user
      * @param t   The Exception to log in the message
+ 	 * Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
      */
     protected void finish(String msg, Throwable t) {
         log.info("Finishing job");
@@ -336,8 +338,16 @@
             }
 
             if (success) {
+ 
+				//
+				// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+				// @since $DatabaseSchema  $Date$
+				//  get SetupValues from mapped  SetupContext in DBObject 
+				//  important for application which use different database context for setupValues 
+				//
                 // we only notify on success if there is a special setup value set to true
-                String isNotify = Setup.getValueUnrequired(getDataContext(), IS_NOTIFY_ON_JOB_SUCCESS);
+//				String isNotify = Setup.getValueUnrequired(getDataContext(), IS_NOTIFY_ON_JOB_SUCCESS);
+                String isNotify = Setup.getValueUnrequired(getSetupContext(), IS_NOTIFY_ON_JOB_SUCCESS);
                 if (StringUtil.toBoolean(isNotify)) {
                     log.debug("Notifying user " + u.getUid() +
                             " that job completed successfully");
@@ -514,6 +524,25 @@
     protected String getDataContext() throws DBException {
         return getJobQueueEntry().getDataContext();
     }
+
+	/**
+	 * Retrieve the data context of the job
+	 *
+	 * @return java.lang.String
+	 * Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
+	*/
+	protected String getSetupContext() throws DBException {
+	
+		//
+		// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+		// @since $DatabaseSchema  $Date$
+		//  get SetupValues from mapped  SetupContext in DBObject 
+		//  important for application which use different database context for setupValues 
+		//
+	
+	    return getJobQueueEntry().getSetupContext();
+	}
 
     /**
      * Tell this Job object what Schema it belongs to. This is used
Index: ConfigContext.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/ConfigContext.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/ConfigContext.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/ConfigContext.java -u -r1.13 -r1.14
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/ConfigContext.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/ConfigContext.java
@@ -183,6 +183,11 @@
 	/**
 	 * Context to use for accessing cache values for this context.
 	 */
+	private String cacheContext = null;
+
+	/**
+	 * Context to use for accessing setup values for this context.
+	 */
 	private String setupContext = null;
 
     public ConfigContext() {
@@ -412,13 +417,42 @@
 		return StringUtil.toBoolean(hasSetupValues);
 	}
 
+
+	/**
+	 * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	*  @since $DatabaseSchema  $Date$
+	*/
 	public String getSetupContext() {
 		return setupContext;
 	}
 
+
+	/**
+	 * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	*  @since $DatabaseSchema  $Date$
+	*/
+	public String getCacheContext() {
+		return cacheContext;
+	}
+
+
+	/**
+	 * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	*  @since $DatabaseSchema  $Date$
+	*/
 	public void setSetupContext(String newSetupContextName) {
 		StringUtil.assertNotBlank(newSetupContextName, "You must specify a setup context name");
 		setupContext = newSetupContextName;
+	}
+
+
+	/**
+	 * Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	*  @since $DatabaseSchema  $Date$
+	*/
+	public void setCacheContext(String newCacheContextName) {
+		StringUtil.assertNotBlank(newCacheContextName, "You must specify a cache context name");
+		cacheContext = newCacheContextName;
 	}
 
 }
Index: EMailSender.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/EMailSender.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/EMailSender.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/EMailSender.java -u -r1.27 -r1.28
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/EMailSender.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/misc/EMailSender.java
@@ -410,12 +410,26 @@
      * the value is retrieved from the setting of the MAILPassword Setup parameter.
      *
      * @return SMTP password
+ 	 * Modify by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+	 * @since $DatabaseSchema  $Date$
      */
     private String getSMTPPassword() {
         String myPassword = password;
         if (myPassword == null) {
-            myPassword = Setup.getValueUnrequired(getDataContext(),
-                    "MAILPassword");
+ 
+			//
+			// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+			// @since $DatabaseSchema  $Date$
+			//  get SetupValues from mapped  SetupContext in DBObject 
+			//  important for application which use different database context for setupValues 
+			//
+
+//			myPassword = Setup.getValueUnrequired(getDataContext(),	"MAILPassword");
+        	try {
+				myPassword = Setup.getValueUnrequired(ConfigManager.getContext(getDataContext()).getSetupContext(),	"MAILPassword");
+        	} catch (ConfigurationException ce) {
+        		ce.printStackTrace();
+        	}
         }
 
         password = myPassword;
Index: expresso-config_4_0.dtd
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/expresso-config_4_0.dtd,v
retrieving revision 1.11
retrieving revision 1.12
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/expresso-config_4_0.dtd -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/expresso-config_4_0.dtd -u -r1.11 -r1.12
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/expresso-config_4_0.dtd
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/expresso-config_4_0.dtd
@@ -7,7 +7,7 @@
 
      <!DOCTYPE expresso-config PUBLIC
        "-//Jcorporate Ltd//DTD Expresso Configuration 1.0//EN"
-       "http://www.jcorporate.com/dtds/expresso-config_1_0.dtd">
+       "http://www.jcorporate.com/dtds/expresso-config_4_0.dtd">
 -->
 <!-- ========== Defined Types ============================================= -->
 <!-- A "Boolean" is the string representation of a boolean (true or false)
@@ -44,6 +44,7 @@
 <!ELEMENT hasSetupTables (#PCDATA)>
 <!ELEMENT hasSetupValues (#PCDATA)>
 <!ELEMENT cacheContext (#PCDATA)>
+<!ELEMENT setupContext (#PCDATA)>
 <!ELEMENT httpPort (#PCDATA)>
 <!ELEMENT sslPort (#PCDATA)>
 <!ELEMENT class-handlers (class-handler)+>
@@ -61,80 +62,86 @@
      with one database (or other persistant store) and a user is logged in to one specific context
      at a time -->
 <!ENTITY % contextName "CDATA">
-<!ELEMENT context (description?, hasSetupTables?, hasSetupValues?, cacheContext?, jdbc?, type-mapping*, images, startJobHandler?, showStackTrace?, mailDebug?, customProperty*, path-mappings*, expressoDir?, setupDefault*)>
+<!ELEMENT context (description?, hasSetupTables?, hasSetupValues?, cacheContext?, setupContext?, jdbc?, type-mapping*, images, startJobHandler?, showStackTrace?, mailDebug?, customProperty*, path-mappings*, expressoDir?, setupDefault*)>
 <!ATTLIST context
-id ID #IMPLIED
-name %contextName; #REQUIRED
-active %Boolean; #IMPLIED
-setup CDATA #IMPLIED
-language CDATA #IMPLIED
-country CDATA #IMPLIED
-minPasswordSize CDATA #IMPLIED
-styleSheet CDATA #IMPLIED
-useEmailAsLogin %Boolean; #IMPLIED
-useSSL %Boolean; #IMPLIED
+	id ID #IMPLIED
+	name %contextName; #REQUIRED
+	active %Boolean; #IMPLIED
+	setup CDATA #IMPLIED
+	language CDATA #IMPLIED
+	country CDATA #IMPLIED
+	minPasswordSize CDATA #IMPLIED
+	styleSheet CDATA #IMPLIED
+	useEmailAsLogin %Boolean; #IMPLIED
+	useSSL %Boolean; #IMPLIED
 >
 <!ELEMENT setupDefault EMPTY>
 <!ATTLIST setupDefault
-schema CDATA #REQUIRED
-name CDATA #REQUIRED
-value CDATA #REQUIRED
+	schema CDATA #REQUIRED
+	name CDATA #REQUIRED
+	value CDATA #REQUIRED
 >
 <!ELEMENT description (#PCDATA)>
 <!ELEMENT expressoDir (#PCDATA)>
 <!-- The "jdbc" sub-element of the context element specifies the connect information for a JDBC data source -->
 <!ELEMENT jdbc (dbWildcard*, jndi?)>
 <!ATTLIST jdbc
-driverType %DriverType; #IMPLIED
-driver CDATA #REQUIRED
-url CDATA #REQUIRED
-connectFormat %ConnectFormat; #REQUIRED
-login CDATA #REQUIRED
-password CDATA #REQUIRED
-cache %Boolean; #REQUIRED
-dbTest CDATA #IMPLIED
-dateSelectFormat CDATA #IMPLIED
-dateSelectFunction CDATA #IMPLIED
-dateUpdateFormat CDATA #IMPLIED
-dateUpdateFunction CDATA #IMPLIED
-timeSelectFormat CDATA #IMPLIED
-timeSelectFunction CDATA #IMPLIED
-timeUpdateFormat CDATA #IMPLIED
-timeUpdateFunction CDATA #IMPLIED
-dateTimeSelectFormat CDATA #IMPLIED
-dateTimeSelectFunction CDATA #IMPLIED
-dateTimeUpdateFormat CDATA #IMPLIED
-dateTimeUpdateFunction CDATA #IMPLIED
-dbStats %Boolean; #IMPLIED
-createTableIndicies %Boolean; #IMPLIED
-limitationPosition CDATA #IMPLIED
-limitationSyntax CDATA #IMPLIED
-uniqueRowKeyword CDATA #IMPLIED
-checkZeroUpdate %Boolean; #IMPLIED
-useNullOnCreate %Boolean; #IMPLIED
-hasBooleanType %Boolean; #IMPLIED
-skipText %Boolean; #IMPLIED
-escapeHandler CDATA #IMPLIED
-nativeBlob %Boolean; #IMPLIED
-dbCatalogue CDATA #IMPLIED
-dbSchema CDATA #IMPLIED
-transactionNotActive %Boolean; #IMPLIED
-stringNotTrim %Boolean; #IMPLIED
+	driverType %DriverType; #IMPLIED
+	driver CDATA #REQUIRED
+	url CDATA #REQUIRED
+	connectFormat %ConnectFormat; #REQUIRED
+	login CDATA #REQUIRED
+	password CDATA #REQUIRED
+	cache %Boolean; #REQUIRED
+	dbTest CDATA #IMPLIED
+	dateDisplayFormat CDATA #IMPLIED
+	dateDisplayFunction CDATA #IMPLIED
+	dateSelectFormat CDATA #IMPLIED
+	dateSelectFunction CDATA #IMPLIED
+	dateUpdateFormat CDATA #IMPLIED
+	dateUpdateFunction CDATA #IMPLIED
+	timeDisplayFormat CDATA #IMPLIED
+	timeDisplayFunction CDATA #IMPLIED
+	timeSelectFormat CDATA #IMPLIED
+	timeSelectFunction CDATA #IMPLIED
+	timeUpdateFormat CDATA #IMPLIED
+	timeUpdateFunction CDATA #IMPLIED
+	dateTimeDisplayFormat CDATA #IMPLIED
+	dateTimeDisplayFunction CDATA #IMPLIED
+	dateTimeSelectFormat CDATA #IMPLIED
+	dateTimeSelectFunction CDATA #IMPLIED
+	dateTimeUpdateFormat CDATA #IMPLIED
+	dateTimeUpdateFunction CDATA #IMPLIED
+	dbStats %Boolean; #IMPLIED
+	createTableIndicies %Boolean; #IMPLIED
+	limitationPosition CDATA #IMPLIED
+	limitationSyntax CDATA #IMPLIED
+	uniqueRowKeyword CDATA #IMPLIED
+	checkZeroUpdate %Boolean; #IMPLIED
+	useNullOnCreate %Boolean; #IMPLIED
+	hasBooleanType %Boolean; #IMPLIED
+	skipText %Boolean; #IMPLIED
+	escapeHandler CDATA #IMPLIED
+	nativeBlob %Boolean; #IMPLIED
+	dbCatalogue CDATA #IMPLIED
+	dbSchema CDATA #IMPLIED
+	transactionNotActive %Boolean; #IMPLIED
+	stringNotTrim %Boolean; #IMPLIED
 >
 <!ELEMENT ldap EMPTY>
 <!ATTLIST ldap
-server CDATA #REQUIRED
-user CDATA #REQUIRED
-password CDATA #REQUIRED
-root CDATA #REQUIRED
+	server CDATA #REQUIRED
+	user CDATA #REQUIRED
+	password CDATA #REQUIRED
+	root CDATA #REQUIRED
 >
 <!-- skipText is set if the search criteria for "text" type fields should be ignored for this database -->
 <!-- Don't do it unless you need to -->
 <!ELEMENT dbWildcard (#PCDATA)>
 <!ELEMENT cacheManager EMPTY>
 <!ATTLIST cacheManager
-minMemoryPercentage CDATA #IMPLIED
-maxRetries CDATA #IMPLIED
+	minMemoryPercentage CDATA #IMPLIED
+	maxRetries CDATA #IMPLIED
 >
 <!-- A "customProperty" element specifies an application-specific custom property -->
 <!ELEMENT customProperty (name, value)>
Index: DBConnection.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnection.java,v
retrieving revision 1.59
retrieving revision 1.60
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnection.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnection.java -u -r1.59 -r1.60
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnection.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnection.java
@@ -85,6 +85,7 @@
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Enumeration;
@@ -224,10 +225,16 @@
     private String dateTimeType = DBField.DATETIME_TYPE;
 
     /**
-     * Don't time out this connection - it may take a while
+     * Don't time out this connection - it may take a while use in transaction context
      */
     private boolean immortal = false;
 
+	/**
+	 * Don't time out this connection - it may not take while, but use for basic request directly in connection 
+	 * handler, and to be released manually. It's use outside transaction context and controle by the DBObject.
+	 */
+	private boolean permanent = false;
+
     /**
      * The main Connection Log
      */
@@ -980,6 +987,7 @@
         myConnection = null;
         isConnected = false;
         immortal = false;
+		permanent = false;
     } /* disconnect() */
 
 
@@ -1294,6 +1302,35 @@
         }
     } /* executeProcedure() */
 
+	    /**
+	     * add the actual sql prepared to batch  in preparedStatement
+	     * 
+	     * - use addPreparedStatement volume batch add or update.
+	     *
+	     * @throws DBException If the query fails or is an update query.
+	     * 
+		 *
+		 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 	 * @since Expresso 5.6
+	     */
+	    public synchronized void addPreparedStatement()
+	            throws DBException {
+	        try {
+	            //
+	            //If a prepared statement has been created
+	            //then we assume we want a prepared  statement to add.
+	            //
+	            if (preparedStatement != null) {
+					preparedStatement.addBatch();
+	
+	            }
+	        } catch (SQLException se) {
+	            throw new DBException("Unable to add statement: callableStatment" +
+	                    " (" + myDescription + ", db/context '" +
+	                    getDataContext() + "')", se);
+	        }
+	    } /* addPreparedStatement() */
+
 
     /**
      * Disconnect abandoned connections
@@ -1747,6 +1784,15 @@
         return immortal;
     } /* getImmortal() */
 
+	/**
+	 * Gets whether or not if this connection times out.
+	 *
+	 * @return true if this connection does not time out.
+	 */
+	public boolean getPermanent() {
+	    return permanent;
+	} /* getPermanent() */
+
     /**
      * Fetch the given field of the current row as an integer
      *
@@ -2525,6 +2571,16 @@
         immortal = newImmortal;
     } /* setImmortal(boolean) */
 
+	/**
+	 * Sets this connection to be permanent, ie it never gets removed or
+	 * disconnected
+	 *
+	 * @param newPermanent The new value to set it to.
+	 */
+	public synchronized void setPermanent(boolean newPermanent) {
+	    permanent = newPermanent;
+	} /* setPermanent(boolean) */
+
     /**
      * Set the SQL to be run against the database
      *
@@ -2574,6 +2630,270 @@
         }
     }
 
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementField(int fieldNum) throws DBException {
+			try {
+				preparedStatement.setNull(fieldNum, java.sql.Types.INTEGER);
+			} catch (SQLException se) {
+				throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, Date fieldValue)" +
+						":Could not set Date value" +
+						" (" + myDescription + ")", se.getMessage());
+			}
+		}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementFieldNull(int fieldNum, int sqlType) throws DBException {
+			try {
+				preparedStatement.setNull(fieldNum, sqlType);
+			} catch (SQLException se) {
+				throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, int sqlType)" +
+						":Could not set Date value" +
+						" (" + myDescription + ")", se.getMessage());
+			}
+		}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public synchronized void setPreparedStatementField(int fieldNum, java.sql.Date fieldValue) throws DBException {
+		try {
+			preparedStatement.setDate(fieldNum, fieldValue);
+		} catch (SQLException se) {
+			throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, Date fieldValue)" +
+					":Could not set Date value" +
+					" (" + myDescription + ")", se.getMessage());
+		}
+	}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public synchronized void setPreparedStatementField(int fieldNum, Timestamp fieldValue) throws DBException {
+		try {
+			preparedStatement.setTimestamp(fieldNum, fieldValue);
+		} catch (SQLException se) {
+			throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, Timestamp fieldValue)" +
+					":Could not set Timestamp value" +
+					" (" + myDescription + ")", se.getMessage());
+		}
+	}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public synchronized void setPreparedStatementField(int fieldNum, double fieldValue) throws DBException {
+		try {
+			preparedStatement.setDouble(fieldNum, fieldValue);
+		} catch (SQLException se) {
+			throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, double fieldValue)" +
+					":Could not set Date value" +
+					" (" + myDescription + ")", se.getMessage());
+		}
+	}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public synchronized void setPreparedStatementField(int fieldNum, float fieldValue) throws DBException {
+		try {
+			preparedStatement.setFloat(fieldNum, fieldValue);
+		} catch (SQLException se) {
+			throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, float fieldValue)" +
+					":Could not set Date value" +
+					" (" + myDescription + ")", se.getMessage());
+		}
+	}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public synchronized void setPreparedStatementField(int fieldNum, int fieldValue) throws DBException {
+		try {
+			preparedStatement.setInt(fieldNum, fieldValue);
+		} catch (SQLException se) {
+			throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, int fieldValue)" +
+					":Could not set Date value" +
+					" (" + myDescription + ")", se.getMessage());
+		}
+	}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public synchronized void setPreparedStatementField(int fieldNum, long fieldValue) throws DBException {
+		try {
+			preparedStatement.setLong(fieldNum, fieldValue);
+		} catch (SQLException se) {
+			throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, long fieldValue)" +
+					":Could not set Date value" +
+					" (" + myDescription + ")", se.getMessage());
+		}
+	}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+	public synchronized void setPreparedStatementField(int fieldNum, String fieldValue) throws DBException {
+		try {
+			preparedStatement.setString(fieldNum, fieldValue);
+		} catch (SQLException se) {
+			throw new DBException(THIS_CLASS + "setPreparedStatementField(int fieldNum, String fieldValue)" +
+					":Could not set Date value" +
+					" (" + myDescription + ")", se.getMessage());
+		}
+	}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementFieldNullTimestamp(int fieldNum) throws DBException {
+			setPreparedStatementFieldNull(fieldNum, java.sql.Types.TIMESTAMP);
+		}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementFieldNullDouble(int fieldNum) throws DBException {
+			setPreparedStatementFieldNull(fieldNum, java.sql.Types.INTEGER);
+		}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementFieldNullFloat(int fieldNum) throws DBException {
+			setPreparedStatementFieldNull(fieldNum, java.sql.Types.FLOAT);
+		}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementFieldNullDecimal(int fieldNum) throws DBException {
+			setPreparedStatementFieldNull(fieldNum, java.sql.Types.DECIMAL);
+		}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementFieldNullDate(int fieldNum) throws DBException {
+			setPreparedStatementFieldNull(fieldNum, java.sql.Types.DATE);
+		}
+
+	/**
+	 * Helper function that avoids all the processing associated with listeners... just set's the
+	 * field data in raw form
+	 *
+	 * @param fieldName  The name of the field to set
+	 * @param fieldValue the value to set it to.
+	 *
+	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+	 * @since Expresso 5.6
+	 */
+		public synchronized void setPreparedStatementFieldNullSmallint(int fieldNum) throws DBException {
+			setPreparedStatementFieldNull(fieldNum, java.sql.Types.SMALLINT);
+		}
+
     /**
      * Retrieve the data context name we're associated with
      *
@@ -2592,6 +2912,19 @@
         return parentPool;
     }
 
+	/**
+	 * Retrieve PreparedStatement previously set for localConnection
+	 *
+	 * @return PreparedStatement (may be null if nobody owns this object)
+	 * 
+	 *
+ 	 * @author Henri Yves Mensah AMAIZO henri-yves.amaizo at amycase.com 
+ 	 * @since Expresso 5.6
+	 */
+	public PreparedStatement getPreparedStatement() {
+	    return preparedStatement;
+	}
+
     /**
      * Sets the parentPool... this is done by the DBConnecitonPool object.
      *
@@ -2753,6 +3086,39 @@
             throw new DBException("", se);
         }
     }
+
+	/**
+	 * Set EXPRESSO permanent mode for the current DBConnection to be used for long request and
+	 * manual released back to the pool.
+	 * <p/>
+	 * author Yves Henri AMAIZO, Thu April 28 22:30:59 2005
+	 *
+	 * @since Expresso 5.6
+	 */
+	public void setConnectionPermanent() throws DBException {
+	
+	    try {
+	        setPermanent(true);
+			setAutoCommit(true);
+	        
+	    } catch (DBException se) {
+	        throw new DBException("", se);
+	    }
+	}
+
+	/**
+	 * Set EXPRESSO reset permanent mode for the current DBConnection released it back
+	 * <p/>
+	 * author Yves Henri AMAIZO, Thu April 28 22:30:59 2005
+	 *
+	 * @since Expresso 5.6
+	 */
+	public void resetConnectionPermanent() throws DBException {
+	
+		setPermanent(false);
+	    parentPool.release(this);
+	        
+	}
 
     /**
      * Trim or not trim parameter set for this connection
Index: DBConnectionPool.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnectionPool.java,v
retrieving revision 1.58
retrieving revision 1.59
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnectionPool.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnectionPool.java -u -r1.58 -r1.59
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnectionPool.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/DBConnectionPool.java
@@ -544,6 +544,7 @@
      * Iterates once through the available connections and cleans them.
      */
     protected void cleanAvailable() throws ConnectionPoolException {
+		String myName = THIS_CLASS + ".cleanAvailable() : ";
         if (log.isDebugEnabled()) {
             log.debug("Checking available pool for connections to remove");
         }
@@ -560,19 +561,31 @@
                 //it has been idle too long, then we need to kill it so we don't
                 //hand out stale connections in the long run.
                 //
-                if ((dbc.getCreatedTime() + maxttl < startTime) && !dbc.getImmortal()) {
+                if ((dbc.getCreatedTime() + maxttl < startTime) && !dbc.getImmortal() && !dbc.getPermanent()) {
                     try {
                     	if (dbc.isClosed()) {
 							log.error("Error !!!!!!!!: disconnecting the connection '" + dbc.getId() +
 							"' now dead  in pool '" + getDataContext() + "'");
                     	}
                         dbc.disconnect();
+						if (log.isDebugEnabled()) {
+							log.debug(myName + "Connection "
+									+ dbc.getDescription() + " '" + dbc.getId() + "'"
+									+ " is available and has been disconnected "
+									+ " because too long time idle and is probably in corrupted ");
+						}
                     } catch (Throwable ex) {
                         log.warn("Error disconnecting", ex);
                     }
 
                     available.remove(i);
                     removedConnections = true;
+					if (log.isDebugEnabled()) {
+						log.debug(myName + "Connection "
+								+ dbc.getDescription() + " '" + dbc.getId() + "'"
+								+ " removed from available queue "
+								+ " because too long time idle and is probably in corrupted ");
+					}
                 } else {
                     i++;
                 }
@@ -596,9 +609,10 @@
      */
     public void clean()
             throws ConnectionPoolException, DBException {
+         String myName = THIS_CLASS + ".clean() : ";
 
         if (log.isDebugEnabled()) {
-            log.debug("Checking connection pool for stale connections");
+            log.debug(myName + "Checking connection pool for stale connections");
         }
 
         long now = System.currentTimeMillis();
@@ -617,7 +631,7 @@
             for (Iterator it = inUse.values().iterator(); it.hasNext();) {
                 oneConnection = (DBConnection) it.next();
                 if (log.isDebugEnabled()) {
-                    log.debug("Checking '"
+                    log.debug(myName + "Checking '"
                             + oneConnection.getDescription() + "'");
                 }
 
@@ -627,12 +641,12 @@
                 if (now > timeOutTime) {
                     /* it's been too long */
                     if (log.isDebugEnabled()) {
-                        log.debug("Checking to close connection");
+                        log.debug(myName + "Checking to close connection");
                     }
 
-                    if (!oneConnection.getImmortal()) {
+                    if (!oneConnection.getImmortal() && !oneConnection.getPermanent()) {
                         if (log.isDebugEnabled()) {
-                            log.debug("Connection "
+                            log.debug(myName + "Connection "
                                     + oneConnection.getDescription() + " '" + oneConnection.getId() + "'"
                                     + " was idle more than " + (interval / 1000)
                                     + " seconds and was returned to the pool. "
@@ -646,7 +660,7 @@
                         connectionsToRelease.add(oneConnection);
 
                     } else {
-                        log.warn("Warning: 'Immortal' Connection "
+                        log.warn(myName + "Warning: 'Immortal or Permanent' Connection "
                                 + oneConnection.getDescription() + " '" + oneConnection.getId() + "'"
                                 + " was idle more than " + (interval / 1000)
                                 + " seconds. "
@@ -660,18 +674,18 @@
 
                 /* If the connection is (interval * 3) MINUTES old, then close it */
                 timeOutTime = lastTouched + (interval * 60 * 3);
-                if (now > timeOutTime && !oneConnection.getImmortal()) {
+                if (now > timeOutTime && !oneConnection.getImmortal() && !oneConnection.getPermanent()) {
                     /* set this boolean to true, so that the connections are removed after iteration*/
                     bCheckToRemove = true;
 					if (log.isDebugEnabled()) {
-						log.debug("Connection "
+						log.debug(myName + "Connection "
 								+ oneConnection.getDescription() + " '" + oneConnection.getId() + "'"
 								+ " was idle more than " + (interval * 60 * 3 / 1000)
 								+ " minutes and was disconnected and removed "
 								+ "from the pool");
 					}
 
-                    log.warn("Connection "
+                    log.warn(myName + "Connection "
 							+ oneConnection.getDescription() + " '" + oneConnection.getId() + "'"
                             + " was idle more than " + (interval * 60 * 3 / 1000)
                             + " minutes and was disconnected and removed "
@@ -696,14 +710,14 @@
 					if (!oneConnection.getAutoCommit()) {
 						oneConnection.rollback();
 						if (log.isDebugEnabled()) {
-							log.debug("Connection <in Transaction Mode> <not immortal>"
+							log.debug(myName + "Connection <in Transaction Mode> <not immortal or permanent>"
 									+ oneConnection.getDescription() + " '" + oneConnection.getId() + "'"
 									+ " is rolled back because idle more than and not immortal" + (interval * 60 * 3 / 1000)
 									+ " minutes and will be disconnected and removed "
 									+ "from the pool");
 						}
 
-						log.warn("Connection <in Transaction Mode> <not immortal>"
+						log.warn(myName + "Connection <in Transaction Mode> <not immortal or permanent>"
 								+ oneConnection.getDescription() + " '" + oneConnection.getId() + "'"
 								+ oneConnection.getDescription()
 								+ " is rolled back because idle more than and not immortal" + (interval * 60 * 3 / 1000)
@@ -722,6 +736,12 @@
                     dbconn.disconnect();
                     dbconn.setAvailable(true);
                     inUse.remove(new Integer(dbconn.getId()));
+					if (log.isDebugEnabled()) {
+						log.debug(myName + "Connection "
+								+ dbconn.getDescription() + " '" + dbconn.getId() + "'"
+								+ " used has set to be disconnected and removed "
+								+ "from the pool");
+					}
                 }
             }
 
@@ -734,6 +754,11 @@
                     oneToRelease = (DBConnection) rl.next();
                     release(oneToRelease);
                     oneToRelease.clear();
+					if (log.isDebugEnabled()) {
+						log.debug(myName + "Connection "
+								+ oneToRelease.getDescription() + " '" + oneToRelease.getId() + "'"
+								+ "  released and cleared ");
+					}
                     oneToRelease = null;
                 }
             }
@@ -848,6 +873,7 @@
      */
     private DBConnection findExistingConnection() {
         DBConnection oneConnection = null;
+		String myName = THIS_CLASS + ".findExistingConnection() : ";
 
         try {
             while (available.size() > 0) {
Index: TableCreator.java
===================================================================
RCS file: /home/javacorp/.cvs/expresso/expresso/expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/TableCreator.java,v
retrieving revision 1.25
retrieving revision 1.26
diff -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/TableCreator.java -Lexpresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/TableCreator.java -u -r1.25 -r1.26
--- expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/TableCreator.java
+++ expresso-web/WEB-INF/src/com/jcorporate/expresso/core/db/TableCreator.java
@@ -316,7 +316,14 @@
         }
         sqlStatement.append("CREATE");
         if ("org.hsqldb.jdbcDriver".equals(myConfig.getDriver())) {
-            // add development option where we want all data NOT in
+ 
+			//
+			// Created by Yves Henri AMAIZO <amy_amaizo at compuserve.com>
+			// @since $DatabaseSchema  $Date$
+			//  get SetupValues from mapped  SetupContext in DBObject 
+			//  important for application which use different database context for setupValues 
+			//
+           // add development option where we want all data NOT in
             // editable text format, but rather cached for efficiency in a .data table
             String useCachedHSQL = Setup.getValueUnrequired(dbObj.getDataContext(), USE_CACHED_HSQL);
             if (StringUtil.toBoolean(useCachedHSQL)) {


More information about the cvs mailing list