merged with 1.1
[mir.git] / source / mir / storage / Database.java
index 4af1769..468c06b 100755 (executable)
@@ -1,5 +1,5 @@
 /*\r
- * Copyright (C) 2001, 2002  The Mir-coders group\r
+ * Copyright (C) 2001, 2002 The Mir-coders group\r
  *\r
  * This file is part of Mir.\r
  *\r
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
  *\r
  * In addition, as a special exception, The Mir-coders gives permission to link\r
- * the code of this program with the com.oreilly.servlet library, any library\r
- * licensed under the Apache Software License, The Sun (tm) Java Advanced\r
- * Imaging library (JAI), The Sun JIMI library (or with modified versions of\r
- * the above that use the same license as the above), and distribute linked\r
- * combinations including the two.  You must obey the GNU General Public\r
- * License in all respects for all of the code used other than the above\r
- * mentioned libraries.  If you modify this file, you may extend this exception\r
- * to your version of the file, but you are not obligated to do so.  If you do\r
- * not wish to do so, delete this exception statement from your version.\r
+ * the code of this program with  any library licensed under the Apache Software License,\r
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
+ * (or with modified versions of the above that use the same license as the above),\r
+ * and distribute linked combinations including the two.  You must obey the\r
+ * GNU General Public License in all respects for all of the code used other than\r
+ * the above mentioned libraries.  If you modify this file, you may extend this\r
+ * exception to your version of the file, but you are not obligated to do so.\r
+ * If you do not wish to do so, delete this exception statement from your version.\r
  */\r
-\r
 package mir.storage;\r
 \r
-import  java.sql.*;\r
-import  java.lang.*;\r
-import  java.io.*;\r
-import  java.util.*;\r
-import  java.text.SimpleDateFormat;\r
-import  java.text.ParseException;\r
-import  freemarker.template.*;\r
-import  com.codestudio.sql.*;\r
-import  com.codestudio.util.*;\r
-\r
-import  mir.storage.StorageObject;\r
-import  mir.storage.store.*;\r
-import  mir.entity.*;\r
-import  mir.misc.*;\r
-import  mir.util.*;\r
+import java.io.IOException;\r
+import java.io.InputStreamReader;\r
+import java.sql.Connection;\r
+import java.sql.PreparedStatement;\r
+import java.sql.ResultSet;\r
+import java.sql.ResultSetMetaData;\r
+import java.sql.SQLException;\r
+import java.sql.Statement;\r
+import java.sql.Timestamp;\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
+import java.util.Calendar;\r
+import java.util.GregorianCalendar;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.TimeZone;\r
+import java.util.Vector;\r
+\r
+import com.codestudio.util.SQLManager;\r
+import mir.config.MirPropertiesConfiguration;\r
+import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;\r
+import mir.entity.Entity;\r
+import mir.entity.EntityList;\r
+import mir.entity.StorableObjectEntity;\r
+import mir.log.LoggerWrapper;\r
+import mir.misc.StringUtil;\r
+import mir.storage.store.ObjectStore;\r
+import mir.storage.store.StorableObject;\r
+import mir.storage.store.StoreContainerType;\r
+import mir.storage.store.StoreIdentifier;\r
+import mir.storage.store.StoreUtil;\r
+import mir.util.JDBCStringRoutines;\r
 \r
 \r
 /**\r
@@ -56,110 +74,123 @@ import  mir.util.*;
  * Treiber, Host, User und Passwort, ueber den der Zugriff auf die\r
  * Datenbank erfolgt.\r
  *\r
- * @version $Id: Database.java,v 1.30 2002/12/28 03:21:38 mh Exp $\r
+ * @version $Id: Database.java,v 1.46 2003/09/03 18:29:03 zapata Exp $\r
  * @author rk\r
  *\r
  */\r
 public class Database implements StorageObject {\r
+  private static Class GENERIC_ENTITY_CLASS = mir.entity.StorableObjectEntity.class;\r
+  private static Class STORABLE_OBJECT_ENTITY_CLASS = mir.entity.StorableObjectEntity.class;\r
 \r
-  protected String                    theTable;\r
-  protected String                    theCoreTable=null;\r
-  protected String                    thePKeyName="id";\r
-  protected int                       thePKeyType, thePKeyIndex;\r
-  protected boolean                   evaluatedMetaData=false;\r
-  protected ArrayList                 metadataFields,metadataLabels,\r
-  metadataNotNullFields;\r
-  protected int[]                     metadataTypes;\r
-  protected Class                     theEntityClass;\r
-  protected StorageObject             myselfDatabase;\r
-  protected SimpleList                popupCache=null;\r
-  protected boolean                   hasPopupCache = false;\r
-  protected SimpleHash                hashCache=null;\r
-  protected boolean                   hasTimestamp=true;\r
-  private String                      database_driver, database_url;\r
-  private int                         defaultLimit;\r
-  protected DatabaseAdaptor           theAdaptor;\r
-  protected Logfile                   theLog;\r
-  private static Class                GENERIC_ENTITY_CLASS=null,\r
-  STORABLE_OBJECT_ENTITY_CLASS=null;\r
-  private static SimpleHash           POPUP_EMTYLINE=new SimpleHash();\r
-  protected static final ObjectStore  o_store=ObjectStore.getInstance();\r
-  private SimpleDateFormat _dateFormatterOut =\r
-      new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");\r
-  private SimpleDateFormat _dateFormatterIn =\r
-      new SimpleDateFormat("yyyy-MM-dd HH:mm");\r
-  private Calendar _cal = new GregorianCalendar();\r
 \r
+  private static Map POPUP_EMPTYLINE = new HashMap();\r
+  protected static final ObjectStore o_store = ObjectStore.getInstance();\r
   private static final int _millisPerHour = 60 * 60 * 1000;\r
   private static final int _millisPerMinute = 60 * 1000;\r
 \r
   static {\r
     // always same object saves a little space\r
-    POPUP_EMTYLINE.put("key", ""); POPUP_EMTYLINE.put("value", "--");\r
-    try {\r
-      GENERIC_ENTITY_CLASS = Class.forName("mir.entity.StorableObjectEntity");\r
-      STORABLE_OBJECT_ENTITY_CLASS = Class.forName("mir.entity.StorableObjectEntity");\r
-    }\r
-    catch (Exception e) {\r
-      System.err.println("FATAL: Database.java could not initialize" + e.getMessage());\r
-    }\r
+    POPUP_EMPTYLINE.put("key", "");\r
+    POPUP_EMPTYLINE.put("value", "--");\r
   }\r
 \r
+  protected LoggerWrapper logger;\r
+  protected MirPropertiesConfiguration configuration;\r
+  protected String theTable;\r
+  protected String theCoreTable = null;\r
+  protected String thePKeyName = "id";\r
+  protected int thePKeyType;\r
+  protected int thePKeyIndex;\r
+  protected boolean evaluatedMetaData = false;\r
+  protected ArrayList metadataFields;\r
+  protected ArrayList metadataLabels;\r
+  protected ArrayList metadataNotNullFields;\r
+  protected int[] metadataTypes;\r
+  protected Class theEntityClass;\r
+  protected List popupCache = null;\r
+  protected boolean hasPopupCache = false;\r
+  protected Map hashCache = null;\r
+  protected boolean hasTimestamp = true;\r
+  private String database_driver;\r
+  private String database_url;\r
+  private int defaultLimit;\r
+\r
+  TimeZone timezone;\r
+  SimpleDateFormat internalDateFormat;\r
+  SimpleDateFormat userInputDateFormat;\r
+/*\r
+  private SimpleDateFormat _dateFormatterOut;\r
+  private SimpleDateFormat _dateFormatterIn;\r
+  _dateFormatterOut = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");\r
+  _dateFormatterIn = new SimpleDateFormat("yyyy-MM-dd HH:mm");\r
+*/\r
 \r
   /**\r
-   * Kontruktor bekommt den Filenamen des Konfigurationsfiles übergeben.\r
+   * Kontruktor bekommt den Filenamen des Konfigurationsfiles ?bergeben.\r
    * Aus diesem file werden <code>Database.Logfile</code>,\r
    * <code>Database.Username</code>,<code>Database.Password</code>,\r
    * <code>Database.Host</code> und <code>Database.Adaptor</code>\r
-   * ausgelesen und ein Broker für die Verbindugen zur Datenbank\r
+   * ausgelesen und ein Broker f?r die Verbindugen zur Datenbank\r
    * erzeugt.\r
    *\r
    * @param   String confFilename Dateiname der Konfigurationsdatei\r
    */\r
-  public Database() throws StorageObjectException {\r
-    theLog = Logfile.getInstance(MirConfig.getProp("Home")+\r
-                                 MirConfig.getProp("Database.Logfile"));\r
-    String theAdaptorName=MirConfig.getProp("Database.Adaptor");\r
-    defaultLimit = Integer.parseInt(MirConfig.getProp("Database.Limit"));\r
+  public Database() throws StorageObjectFailure {\r
+    try {\r
+      configuration = MirPropertiesConfiguration.instance();\r
+    }\r
+    catch (PropertiesConfigExc e) {\r
+      throw new StorageObjectFailure(e);\r
+    }\r
+    logger = new LoggerWrapper("Database");\r
+    timezone = TimeZone.getTimeZone(configuration.getString("Mir.DefaultTimezone"));\r
+    internalDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");\r
+    internalDateFormat.setTimeZone(timezone);\r
+\r
+    userInputDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");\r
+    userInputDateFormat.setTimeZone(timezone);\r
+\r
+\r
+    String theAdaptorName = configuration.getString("Database.Adaptor");\r
+    defaultLimit = Integer.parseInt(configuration.getString("Database.Limit"));\r
+\r
     try {\r
       theEntityClass = GENERIC_ENTITY_CLASS;\r
-      theAdaptor = (DatabaseAdaptor)Class.forName(theAdaptorName).newInstance();\r
-    } catch (Exception e){\r
-      theLog.printError("Error in Database() constructor with "+\r
-                        theAdaptorName + " -- " +e.getMessage());\r
-      throw new StorageObjectException("Error in Database() constructor with "\r
-                                       +e.getMessage());\r
+    }\r
+    catch (Throwable e) {\r
+      logger.error("Error in Database() constructor with " + theAdaptorName + " -- " + e.getMessage());\r
+      throw new StorageObjectFailure("Error in Database() constructor.", e);\r
     }\r
   }\r
 \r
   /**\r
-   * Liefert die Entity-Klasse zurück, in der eine Datenbankzeile gewrappt\r
-   * wird. Wird die Entity-Klasse durch die erbende Klasse nicht überschrieben,\r
+   * Liefert die Entity-Klasse zur?ck, in der eine Datenbankzeile gewrappt\r
+   * wird. Wird die Entity-Klasse durch die erbende Klasse nicht ?berschrieben,\r
    * wird eine mir.entity.GenericEntity erzeugt.\r
    *\r
    * @return Class-Objekt der Entity\r
    */\r
-  public java.lang.Class getEntityClass () {\r
-    return  theEntityClass;\r
+  public java.lang.Class getEntityClass() {\r
+    return theEntityClass;\r
   }\r
 \r
   /**\r
-   * Liefert die Standardbeschränkung von select-Statements zurück, also\r
-   * wieviel Datensätze per Default selektiert werden.\r
+   * Liefert die Standardbeschr?nkung von select-Statements zur?ck, also\r
+   * wieviel Datens?tze per Default selektiert werden.\r
    *\r
-   * @return Standard-Anzahl der Datensätze\r
+   * @return Standard-Anzahl der Datens?tze\r
    */\r
-  public int getLimit () {\r
-    return  defaultLimit;\r
+  public int getLimit() {\r
+    return defaultLimit;\r
   }\r
 \r
   /**\r
-   * Liefert den Namen des Primary-Keys zurück. Wird die Variable nicht von\r
-   * der erbenden Klasse überschrieben, so ist der Wert <code>PKEY</code>\r
+   * Liefert den Namen des Primary-Keys zur?ck. Wird die Variable nicht von\r
+   * der erbenden Klasse ?berschrieben, so ist der Wert <code>PKEY</code>\r
    * @return Name des Primary-Keys\r
    */\r
-  public String getIdName () {\r
-    return  thePKeyName;\r
+  public String getIdName() {\r
+    return thePKeyName;\r
   }\r
 \r
   /**\r
@@ -167,21 +198,24 @@ public class Database implements StorageObject {
    *\r
    * @return Name der Tabelle\r
    */\r
-  public String getTableName () {\r
-    return  theTable;\r
+  public String getTableName() {\r
+    return theTable;\r
   }\r
 \r
-      /*\r
+  /*\r
   *   Dient dazu vererbte Tabellen bei objectrelationalen DBMS\r
   *   zu speichern, wenn die id einer Tabelle in der parenttabelle verwaltet\r
   *   wird.\r
   *   @return liefert theCoreTabel als String zurueck, wenn gesetzt, sonst\r
   *    the Table\r
-       */\r
-\r
-  public String getCoreTable(){\r
-    if (theCoreTable!=null) return theCoreTable;\r
-    else return theTable;\r
+   */\r
+  public String getCoreTable() {\r
+    if (theCoreTable != null) {\r
+      return theCoreTable;\r
+    }\r
+    else {\r
+      return theTable;\r
+    }\r
   }\r
 \r
   /**\r
@@ -189,10 +223,12 @@ public class Database implements StorageObject {
    * @return int-Array mit den Typen der Felder\r
    * @exception StorageObjectException\r
    */\r
-  public int[] getTypes () throws StorageObjectException {\r
-    if (metadataTypes == null)\r
+  public int[] getTypes() throws StorageObjectFailure {\r
+    if (metadataTypes == null) {\r
       get_meta_data();\r
-    return  metadataTypes;\r
+    }\r
+\r
+    return metadataTypes;\r
   }\r
 \r
   /**\r
@@ -200,10 +236,12 @@ public class Database implements StorageObject {
    * @return ArrayListe mit Labeln\r
    * @exception StorageObjectException\r
    */\r
-  public ArrayList getLabels () throws StorageObjectException {\r
-    if (metadataLabels == null)\r
+  public List getLabels() throws StorageObjectFailure {\r
+    if (metadataLabels == null) {\r
       get_meta_data();\r
-    return  metadataLabels;\r
+    }\r
+\r
+    return metadataLabels;\r
   }\r
 \r
   /**\r
@@ -211,162 +249,225 @@ public class Database implements StorageObject {
    * @return ArrayList mit Feldern\r
    * @exception StorageObjectException\r
    */\r
-  public ArrayList getFields () throws StorageObjectException {\r
-    if (metadataFields == null)\r
+  public List getFields() throws StorageObjectFailure {\r
+    if (metadataFields == null) {\r
       get_meta_data();\r
-    return  metadataFields;\r
-  }\r
+    }\r
 \r
+    return metadataFields;\r
+  }\r
 \r
-      /*\r
+  /*\r
   *   Gets value out of ResultSet according to type and converts to String\r
   *   @param inValue  Wert aus ResultSet.\r
   *   @param aType  Datenbanktyp.\r
   *   @return liefert den Wert als String zurueck. Wenn keine Umwandlung moeglich\r
   *           dann /unsupported value/\r
-       */\r
-  private String getValueAsString (ResultSet rs, int valueIndex, int aType) throws StorageObjectException {\r
+   */\r
+  private String getValueAsString(ResultSet rs, int valueIndex, int aType)\r
+    throws StorageObjectFailure {\r
     String outValue = null;\r
+\r
     if (rs != null) {\r
       try {\r
         switch (aType) {\r
           case java.sql.Types.BIT:\r
             outValue = (rs.getBoolean(valueIndex) == true) ? "1" : "0";\r
+\r
             break;\r
-          case java.sql.Types.INTEGER:case java.sql.Types.SMALLINT:case java.sql.Types.TINYINT:case java.sql.Types.BIGINT:\r
+\r
+          case java.sql.Types.INTEGER:\r
+          case java.sql.Types.SMALLINT:\r
+          case java.sql.Types.TINYINT:\r
+          case java.sql.Types.BIGINT:\r
+\r
             int out = rs.getInt(valueIndex);\r
-            if (!rs.wasNull())\r
+\r
+            if (!rs.wasNull()) {\r
               outValue = new Integer(out).toString();\r
+            }\r
+\r
             break;\r
+\r
           case java.sql.Types.NUMERIC:\r
+\r
             /** @todo Numeric can be float or double depending upon\r
              *  metadata.getScale() / especially with oracle */\r
             long outl = rs.getLong(valueIndex);\r
-            if (!rs.wasNull())\r
+\r
+            if (!rs.wasNull()) {\r
               outValue = new Long(outl).toString();\r
+            }\r
+\r
             break;\r
+\r
           case java.sql.Types.REAL:\r
+\r
             float tempf = rs.getFloat(valueIndex);\r
+\r
             if (!rs.wasNull()) {\r
               tempf *= 10;\r
               tempf += 0.5;\r
-              int tempf_int = (int)tempf;\r
-              tempf = (float)tempf_int;\r
+\r
+              int tempf_int = (int) tempf;\r
+              tempf = (float) tempf_int;\r
               tempf /= 10;\r
               outValue = "" + tempf;\r
               outValue = outValue.replace('.', ',');\r
             }\r
+\r
             break;\r
+\r
           case java.sql.Types.DOUBLE:\r
+\r
             double tempd = rs.getDouble(valueIndex);\r
+\r
             if (!rs.wasNull()) {\r
               tempd *= 10;\r
               tempd += 0.5;\r
-              int tempd_int = (int)tempd;\r
-              tempd = (double)tempd_int;\r
+\r
+              int tempd_int = (int) tempd;\r
+              tempd = (double) tempd_int;\r
               tempd /= 10;\r
               outValue = "" + tempd;\r
               outValue = outValue.replace('.', ',');\r
             }\r
+\r
             break;\r
-          case java.sql.Types.CHAR:case java.sql.Types.VARCHAR:case java.sql.Types.LONGVARCHAR:\r
+\r
+          case java.sql.Types.CHAR:\r
+          case java.sql.Types.VARCHAR:\r
+          case java.sql.Types.LONGVARCHAR:\r
             outValue = rs.getString(valueIndex);\r
+\r
             break;\r
+\r
           case java.sql.Types.LONGVARBINARY:\r
             outValue = rs.getString(valueIndex);\r
+\r
             break;\r
+\r
           case java.sql.Types.TIMESTAMP:\r
+\r
             // it's important to use Timestamp here as getting it\r
             // as a string is undefined and is only there for debugging\r
             // according to the API. we can make it a string through formatting.\r
             // -mh\r
             Timestamp timestamp = (rs.getTimestamp(valueIndex));\r
-            if(!rs.wasNull()) {\r
+\r
+            if (!rs.wasNull()) {\r
               java.util.Date date = new java.util.Date(timestamp.getTime());\r
-              outValue = _dateFormatterOut.format(date);\r
-              _cal.setTime(date);\r
-              int offset = _cal.get(Calendar.ZONE_OFFSET)+\r
-                           _cal.get(Calendar.DST_OFFSET);\r
-              String tzOffset = StringUtil.zeroPaddingNumber(\r
-                  offset/_millisPerHour,2,2);\r
-              outValue = outValue+"+"+tzOffset;\r
+\r
+              Calendar calendar = new GregorianCalendar();\r
+              calendar.setTime(date);\r
+              calendar.setTimeZone(timezone);\r
+              outValue = internalDateFormat.format(date);\r
+\r
+              int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);\r
+              String tzOffset = StringUtil.zeroPaddingNumber(Math.abs(offset) / _millisPerHour, 2, 2);\r
+\r
+              if (offset<0)\r
+                outValue = outValue + "-";\r
+              else\r
+                outValue = outValue + "+";\r
+              outValue = outValue + tzOffset;\r
             }\r
+\r
             break;\r
+\r
           default:\r
             outValue = "<unsupported value>";\r
-          theLog.printWarning("Unsupported Datatype: at " + valueIndex +\r
-                              " (" + aType + ")");\r
+            logger.warn("Unsupported Datatype: at " + valueIndex + " (" + aType + ")");\r
         }\r
       } catch (SQLException e) {\r
-        throw  new StorageObjectException("Could not get Value out of Resultset -- "\r
-            + e.getMessage());\r
+        throw new StorageObjectFailure("Could not get Value out of Resultset -- ",\r
+          e);\r
       }\r
     }\r
-    return  outValue;\r
+\r
+    return outValue;\r
   }\r
 \r
-      /*\r
+  /*\r
   *   select-Operator um einen Datensatz zu bekommen.\r
   *   @param id Primaerschluessel des Datensatzes.\r
   *   @return liefert EntityObject des gefundenen Datensatzes oder null.\r
-       */\r
-  public Entity selectById(String id)  throws StorageObjectException\r
-  {\r
-    if (id==null||id.equals(""))\r
-      throw new StorageObjectException("id war null");\r
+   */\r
+  public Entity selectById(String id) throws StorageObjectExc {\r
+    if ((id == null) || id.equals("")) {\r
+      throw new StorageObjectExc("Database.selectById: Missing id");\r
+    }\r
 \r
     // ask object store for object\r
-    if ( StoreUtil.implementsStorableObject(theEntityClass) ) {\r
+    if (StoreUtil.implementsStorableObject(theEntityClass)) {\r
       String uniqueId = id;\r
-      if ( theEntityClass.equals(StorableObjectEntity.class) )\r
-        uniqueId+="@"+theTable;\r
+\r
+      if (theEntityClass.equals(StorableObjectEntity.class)) {\r
+        uniqueId += ("@" + theTable);\r
+      }\r
+\r
       StoreIdentifier search_sid = new StoreIdentifier(theEntityClass, uniqueId);\r
-      theLog.printDebugInfo("CACHE: (dbg) looking for sid " + search_sid.toString());\r
-      Entity hit = (Entity)o_store.use(search_sid);\r
-      if ( hit!=null ) return hit;\r
+      logger.debug("CACHE: (dbg) looking for sid " + search_sid.toString());\r
+\r
+      Entity hit = (Entity) o_store.use(search_sid);\r
+\r
+      if (hit != null) {\r
+        return hit;\r
+      }\r
     }\r
 \r
-    Statement stmt=null;Connection con=getPooledCon();\r
-    Entity returnEntity=null;\r
+    Statement stmt = null;\r
+    Connection con = getPooledCon();\r
+    Entity returnEntity = null;\r
+\r
     try {\r
       ResultSet rs;\r
+\r
       /** @todo better prepared statement */\r
-      String selectSql = "select * from " + theTable + " where " + thePKeyName + "=" + id;\r
+      String selectSql =\r
+        "select * from " + theTable + " where " + thePKeyName + "=" + id;\r
       stmt = con.createStatement();\r
       rs = executeSql(stmt, selectSql);\r
+\r
       if (rs != null) {\r
-        if (evaluatedMetaData==false) evalMetaData(rs.getMetaData());\r
-        if (rs.next())\r
+        if (evaluatedMetaData == false) {\r
+          evalMetaData(rs.getMetaData());\r
+        }\r
+\r
+        if (rs.next()) {\r
           returnEntity = makeEntityFromResultSet(rs);\r
-        else theLog.printDebugInfo("Keine daten fuer id: " + id + "in Tabelle" + theTable);\r
+        }\r
+        else {\r
+          logger.debug("No data for id: " + id + " in table " + theTable);\r
+        }\r
+\r
         rs.close();\r
       }\r
       else {\r
-        theLog.printDebugInfo("No Data for Id " + id + " in Table " + theTable);\r
+        logger.debug("No Data for Id " + id + " in Table " + theTable);\r
       }\r
     }\r
-    catch (SQLException sqe){\r
-      throwSQLException(sqe,"selectById"); return null;\r
+    catch (SQLException sqe) {\r
+      throwSQLException(sqe, "selectById");\r
+      return null;\r
     }\r
     catch (NumberFormatException e) {\r
-      theLog.printError("ID ist keine Zahl: " + id);\r
+      logger.error("ID is no number: " + id);\r
+    }\r
+    finally {\r
+      freeConnection(con, stmt);\r
     }\r
-    finally { freeConnection(con,stmt); }\r
 \r
-    /** @todo OS: Entity should be saved in ostore */\r
     return returnEntity;\r
   }\r
 \r
-\r
   /**\r
    *   select-Operator um Datensaetze zu bekommen, die key = value erfuellen.\r
    *   @param key  Datenbankfeld der Bedingung.\r
    *   @param value  Wert die der key anehmen muss.\r
    *   @return EntityList mit den gematchten Entities\r
    */\r
-  public EntityList selectByFieldValue(String aField, String aValue)\r
-      throws StorageObjectException\r
-  {\r
+  public EntityList selectByFieldValue(String aField, String aValue) throws StorageObjectFailure {\r
     return selectByFieldValue(aField, aValue, 0);\r
   }\r
 \r
@@ -377,30 +478,24 @@ public class Database implements StorageObject {
    *   @param offset  Gibt an ab welchem Datensatz angezeigt werden soll.\r
    *   @return EntityList mit den gematchten Entities\r
    */\r
-  public EntityList selectByFieldValue(String aField, String aValue, int offset)\r
-      throws StorageObjectException\r
-  {\r
+  public EntityList selectByFieldValue(String aField, String aValue, int offset) throws StorageObjectFailure {\r
     return selectByWhereClause(aField + "=" + aValue, offset);\r
   }\r
 \r
-\r
   /**\r
-   * select-Operator liefert eine EntityListe mit den gematchten Datensätzen zurück.\r
+   * select-Operator liefert eine EntityListe mit den gematchten Datens?tzen zur?ck.\r
    * Also offset wird der erste Datensatz genommen.\r
    *\r
    * @param wc where-Clause\r
    * @return EntityList mit den gematchten Entities\r
    * @exception StorageObjectException\r
    */\r
-  public EntityList selectByWhereClause(String where)\r
-      throws StorageObjectException\r
-  {\r
+  public EntityList selectByWhereClause(String where) throws StorageObjectFailure {\r
     return selectByWhereClause(where, 0);\r
   }\r
 \r
-\r
   /**\r
-   * select-Operator liefert eine EntityListe mit den gematchten Datensätzen zurück.\r
+   * select-Operator liefert eine EntityListe mit den gematchten Datens?tzen zur?ck.\r
    * Als maximale Anzahl wird das Limit auf der Konfiguration genommen.\r
    *\r
    * @param wc where-Clause\r
@@ -408,15 +503,12 @@ public class Database implements StorageObject {
    * @return EntityList mit den gematchten Entities\r
    * @exception StorageObjectException\r
    */\r
-  public EntityList selectByWhereClause(String whereClause, int offset)\r
-      throws StorageObjectException\r
-  {\r
+  public EntityList selectByWhereClause(String whereClause, int offset) throws StorageObjectFailure {\r
     return selectByWhereClause(whereClause, null, offset);\r
   }\r
 \r
-\r
   /**\r
-   * select-Operator liefert eine EntityListe mit den gematchten Datensätzen zurück.\r
+   * select-Operator liefert eine EntityListe mit den gematchten Datens?tzen zur?ck.\r
    * Also offset wird der erste Datensatz genommen.\r
    * Als maximale Anzahl wird das Limit auf der Konfiguration genommen.\r
    *\r
@@ -425,15 +517,12 @@ public class Database implements StorageObject {
    * @return EntityList mit den gematchten Entities\r
    * @exception StorageObjectException\r
    */\r
-\r
-  public EntityList selectByWhereClause(String where, String order)\r
-      throws StorageObjectException {\r
+  public EntityList selectByWhereClause(String where, String order) throws StorageObjectFailure {\r
     return selectByWhereClause(where, order, 0);\r
   }\r
 \r
-\r
   /**\r
-   * select-Operator liefert eine EntityListe mit den gematchten Datensätzen zurück.\r
+   * select-Operator liefert eine EntityListe mit den gematchten Datens?tzen zur?ck.\r
    * Als maximale Anzahl wird das Limit auf der Konfiguration genommen.\r
    *\r
    * @param wc where-Clause\r
@@ -442,37 +531,33 @@ public class Database implements StorageObject {
    * @return EntityList mit den gematchten Entities\r
    * @exception StorageObjectException\r
    */\r
-\r
-  public EntityList selectByWhereClause(String whereClause, String orderBy, int offset)\r
-      throws StorageObjectException {\r
+  public EntityList selectByWhereClause(String whereClause, String orderBy, int offset) throws StorageObjectFailure {\r
     return selectByWhereClause(whereClause, orderBy, offset, defaultLimit);\r
   }\r
 \r
-\r
   /**\r
-   * select-Operator liefert eine EntityListe mit den gematchten Datensätzen zurück.\r
-   * @param wc where-Clause\r
-   * @param ob orderBy-Clause\r
+   * select-Operator liefert eine EntityListe mit den gematchten Datens?tzen zur?ck.\r
+   * @param aWhereClause where-Clause\r
+   * @param anOrderByClause orderBy-Clause\r
    * @param offset ab welchem Datensatz\r
-   * @param limit wieviele Datensätze\r
+   * @param limit wieviele Datens?tze\r
    * @return EntityList mit den gematchten Entities\r
    * @exception StorageObjectException\r
    */\r
-\r
-  public EntityList selectByWhereClause(String wc, String ob, int offset,\r
-                                        int limit) throws\r
-      StorageObjectException {\r
+  public EntityList selectByWhereClause(String aWhereClause, String anOrderByClause,\r
+            int offset, int limit) throws StorageObjectFailure {\r
 \r
     // check o_store for entitylist\r
     if (StoreUtil.implementsStorableObject(theEntityClass)) {\r
       StoreIdentifier search_sid =\r
-          new StoreIdentifier(theEntityClass,\r
-                              StoreContainerType.STOC_TYPE_ENTITYLIST,\r
-                              StoreUtil.getEntityListUniqueIdentifierFor(\r
-          theTable, wc, ob, offset, limit));\r
+          new StoreIdentifier(\r
+            theEntityClass, StoreContainerType.STOC_TYPE_ENTITYLIST,\r
+            StoreUtil.getEntityListUniqueIdentifierFor(theTable, aWhereClause, anOrderByClause, offset, limit));\r
       EntityList hit = (EntityList) o_store.use(search_sid);\r
+\r
       if (hit != null) {\r
-        theLog.printDebugInfo("CACHE (hit): " + search_sid.toString());\r
+        logger.debug("CACHE (hit): " + search_sid.toString());\r
+\r
         return hit;\r
       }\r
     }\r
@@ -482,30 +567,33 @@ public class Database implements StorageObject {
     Connection con = null;\r
     Statement stmt = null;\r
     ResultSet rs;\r
-    int offsetCount = 0, count = 0;\r
+    int offsetCount = 0;\r
+    int count = 0;\r
 \r
     // build sql-statement\r
 \r
     /** @todo count sql string should only be assembled if we really count\r
      *  see below at the end of method //rk */\r
-\r
-    if (wc != null && wc.length() == 0) {\r
-      wc = null;\r
+    if ((aWhereClause != null) && (aWhereClause.trim().length() == 0)) {\r
+      aWhereClause = null;\r
     }\r
-    StringBuffer countSql = new StringBuffer("select count(*) from ").append(\r
-        theTable);\r
-    StringBuffer selectSql = new StringBuffer("select * from ").append(theTable);\r
-    if (wc != null) {\r
-      selectSql.append(" where ").append(wc);\r
-      countSql.append(" where ").append(wc);\r
+\r
+    StringBuffer countSql =\r
+      new StringBuffer("select count(*) from ").append(theTable);\r
+    StringBuffer selectSql =\r
+      new StringBuffer("select * from ").append(theTable);\r
+\r
+    if (aWhereClause != null) {\r
+      selectSql.append(" where ").append(aWhereClause);\r
+      countSql.append(" where ").append(aWhereClause);\r
     }\r
-    if (ob != null && ! (ob.length() == 0)) {\r
-      selectSql.append(" order by ").append(ob);\r
+\r
+    if ((anOrderByClause != null) && !(anOrderByClause.trim().length() == 0)) {\r
+      selectSql.append(" order by ").append(anOrderByClause);\r
     }\r
-    if (theAdaptor.hasLimit()) {\r
-      if (limit > -1 && offset > -1) {\r
-        selectSql.append(" LIMIT ").append(limit).append(" OFFSET ").append(offset);\r
-      }\r
+\r
+    if ((limit > -1) && (offset > -1)) {\r
+      selectSql.append(" LIMIT ").append(limit).append(" OFFSET ").append(offset);\r
     }\r
 \r
     // execute sql\r
@@ -515,54 +603,69 @@ public class Database implements StorageObject {
 \r
       // selecting...\r
       rs = executeSql(stmt, selectSql.toString());\r
+\r
       if (rs != null) {\r
-        if (!evaluatedMetaData)\r
+        if (!evaluatedMetaData) {\r
           evalMetaData(rs.getMetaData());\r
+        }\r
 \r
         theReturnList = new EntityList();\r
+\r
         Entity theResultEntity;\r
+\r
         while (rs.next()) {\r
           theResultEntity = makeEntityFromResultSet(rs);\r
           theReturnList.add(theResultEntity);\r
           offsetCount++;\r
         }\r
+\r
         rs.close();\r
       }\r
 \r
       // making entitylist infos\r
-      if (! (theAdaptor.hasLimit()))\r
-        count = offsetCount;\r
+      count = offsetCount;\r
 \r
       if (theReturnList != null) {\r
         // now we decide if we have to know an overall count...\r
         count = offsetCount;\r
-        if (limit > -1 && offset > -1) {\r
+\r
+        if ((limit > -1) && (offset > -1)) {\r
           if (offsetCount == limit) {\r
             /** @todo counting should be deffered to entitylist\r
              *  getSize() should be used */\r
             rs = executeSql(stmt, countSql.toString());\r
+\r
             if (rs != null) {\r
-              if (rs.next())\r
+              if (rs.next()) {\r
                 count = rs.getInt(1);\r
+              }\r
+\r
               rs.close();\r
             }\r
-            else\r
-              theLog.printError("Could not count: " + countSql);\r
+            else {\r
+              logger.error("Could not count: " + countSql);\r
+            }\r
           }\r
         }\r
+\r
         theReturnList.setCount(count);\r
         theReturnList.setOffset(offset);\r
-        theReturnList.setWhere(wc);\r
-        theReturnList.setOrder(ob);\r
+        theReturnList.setWhere(aWhereClause);\r
+        theReturnList.setOrder(anOrderByClause);\r
         theReturnList.setStorage(this);\r
         theReturnList.setLimit(limit);\r
-        if (offset >= limit)\r
+\r
+        if (offset >= limit) {\r
           theReturnList.setPrevBatch(offset - limit);\r
-        if (offset + offsetCount < count)\r
+        }\r
+\r
+        if ((offset + offsetCount) < count) {\r
           theReturnList.setNextBatch(offset + limit);\r
+        }\r
+\r
         if (StoreUtil.implementsStorableObject(theEntityClass)) {\r
           StoreIdentifier sid = theReturnList.getStoreIdentifier();\r
-          theLog.printDebugInfo("CACHE (add): " + sid.toString());\r
+          logger.debug("CACHE (add): " + sid.toString());\r
           o_store.add(sid);\r
         }\r
       }\r
@@ -572,68 +675,72 @@ public class Database implements StorageObject {
     }\r
     finally {\r
       try {\r
-        if (con != null)\r
+        if (con != null) {\r
           freeConnection(con, stmt);\r
+        }\r
+      } catch (Throwable t) {\r
       }\r
-      catch (Throwable t) {\r
-      }\r
-\r
     }\r
 \r
     return theReturnList;\r
   }\r
 \r
-\r
   /**\r
    *  Bastelt aus einer Zeile der Datenbank ein EntityObjekt.\r
    *\r
    *  @param rs Das ResultSetObjekt.\r
    *  @return Entity Die Entity.\r
    */\r
-  private Entity makeEntityFromResultSet (ResultSet rs)\r
-      throws StorageObjectException\r
-  {\r
+  private Entity makeEntityFromResultSet(ResultSet rs)\r
+    throws StorageObjectFailure {\r
     /** @todo OS: get Pkey from ResultSet and consult ObjectStore */\r
-    HashMap theResultHash = new HashMap();\r
+    Map theResultHash = new HashMap();\r
     String theResult = null;\r
     int theType;\r
     Entity returnEntity = null;\r
+\r
     try {\r
       int size = metadataFields.size();\r
+\r
       for (int i = 0; i < size; i++) {\r
         // alle durchlaufen bis nix mehr da\r
-\r
         theType = metadataTypes[i];\r
+\r
         if (theType == java.sql.Types.LONGVARBINARY) {\r
-          InputStreamReader is = (InputStreamReader)rs.getCharacterStream(i + 1);\r
+          InputStreamReader is =\r
+            (InputStreamReader) rs.getCharacterStream(i + 1);\r
+\r
           if (is != null) {\r
             char[] data = new char[32768];\r
             StringBuffer theResultString = new StringBuffer();\r
             int len;\r
+\r
             while ((len = is.read(data)) > 0) {\r
               theResultString.append(data, 0, len);\r
             }\r
+\r
             is.close();\r
             theResult = theResultString.toString();\r
-          }\r
-          else {\r
+          } else {\r
             theResult = null;\r
           }\r
-        }\r
-        else {\r
+        } else {\r
           theResult = getValueAsString(rs, (i + 1), theType);\r
         }\r
+\r
         if (theResult != null) {\r
           theResultHash.put(metadataFields.get(i), theResult);\r
         }\r
       }\r
+\r
       if (theEntityClass != null) {\r
-        returnEntity = (Entity)theEntityClass.newInstance();\r
+        returnEntity = (Entity) theEntityClass.newInstance();\r
+        returnEntity.setStorage(this);\r
         returnEntity.setValues(theResultHash);\r
-        returnEntity.setStorage(myselfDatabase);\r
-        if ( returnEntity instanceof StorableObject ) {\r
-          theLog.printDebugInfo("CACHE: ( in) " + returnEntity.getId() + " :"+theTable);\r
-          o_store.add(((StorableObject)returnEntity).getStoreIdentifier());\r
+\r
+        if (returnEntity instanceof StorableObject) {\r
+          logger.debug("CACHE: ( in) " + returnEntity.getId() + " :" + theTable);\r
+          o_store.add(((StorableObject) returnEntity).getStoreIdentifier());\r
         }\r
       } else {\r
         throwStorageObjectException("Internal Error: theEntityClass not set!");\r
@@ -650,59 +757,69 @@ public class Database implements StorageObject {
     }\r
     catch (SQLException sqe) {\r
       throwSQLException(sqe, "makeEntityFromResultSet");\r
-      return  null;\r
+\r
+      return null;\r
     }\r
-    return  returnEntity;\r
+\r
+    return returnEntity;\r
   }\r
 \r
   /**\r
-   * insert-Operator: fügt eine Entity in die Tabelle ein. Eine Spalte WEBDB_CREATE\r
-   * wird automatisch mit dem aktuellen Datum gefuellt.\r
+   * Inserts an entity into the database.\r
    *\r
    * @param theEntity\r
-   * @return der Wert des Primary-keys der eingefügten Entity\r
+   * @return der Wert des Primary-keys der eingef?gten Entity\r
    */\r
-  public String insert (Entity theEntity) throws StorageObjectException {\r
+  public String insert(Entity theEntity) throws StorageObjectFailure {\r
     //cache\r
     invalidatePopupCache();\r
 \r
     // invalidating all EntityLists corresponding with theEntityClass\r
-    if ( StoreUtil.implementsStorableObject(theEntityClass) ) {\r
+    if (StoreUtil.implementsStorableObject(theEntityClass)) {\r
       StoreContainerType stoc_type =\r
-          StoreContainerType.valueOf( theEntityClass,\r
+        StoreContainerType.valueOf(theEntityClass,\r
           StoreContainerType.STOC_TYPE_ENTITYLIST);\r
       o_store.invalidate(stoc_type);\r
     }\r
 \r
     String returnId = null;\r
-    Connection con = null; PreparedStatement pstmt = null;\r
+    Connection con = null;\r
+    PreparedStatement pstmt = null;\r
 \r
     try {\r
-      ArrayList streamedInput = theEntity.streamedInput();\r
+      List streamedInput = theEntity.streamedInput();\r
       StringBuffer f = new StringBuffer();\r
       StringBuffer v = new StringBuffer();\r
-      String aField, aValue;\r
+      String aField;\r
+      String aValue;\r
       boolean firstField = true;\r
+\r
       // make sql-string\r
       for (int i = 0; i < getFields().size(); i++) {\r
-        aField = (String)getFields().get(i);\r
+        aField = (String) getFields().get(i);\r
+\r
         if (!aField.equals(thePKeyName)) {\r
           aValue = null;\r
-          // sonderfaelle\r
-          if (aField.equals("webdb_create") ||\r
-              aField.equals("webdb_lastchange")) {\r
+\r
+          // exceptions\r
+          if (!theEntity.hasValueForField(aField) && (\r
+              aField.equals("webdb_create") ||\r
+              aField.equals("webdb_lastchange"))) {\r
             aValue = "NOW()";\r
           }\r
           else {\r
-            if (streamedInput != null && streamedInput.contains(aField)) {\r
+            if ((streamedInput != null) && streamedInput.contains(aField)) {\r
               aValue = "?";\r
             }\r
             else {\r
               if (theEntity.hasValueForField(aField)) {\r
-                aValue = "'" + JDBCStringRoutines.escapeStringLiteral((String)theEntity.getValue(aField)) + "'";\r
+                aValue =\r
+                  "'" +\r
+                   JDBCStringRoutines.escapeStringLiteral((String) theEntity.getValue(aField)) + "'";\r
               }\r
             }\r
           }\r
+\r
           // wenn Wert gegeben, dann einbauen\r
           if (aValue != null) {\r
             if (firstField == false) {\r
@@ -712,88 +829,107 @@ public class Database implements StorageObject {
             else {\r
               firstField = false;\r
             }\r
+\r
             f.append(aField);\r
             v.append(aValue);\r
           }\r
         }\r
-      }         // end for\r
+      }\r
+       // end for\r
+\r
       // insert into db\r
-      StringBuffer sqlBuf = new StringBuffer("insert into ").append(theTable).append("(").append(f).append(") values (").append(v).append(")");\r
+      StringBuffer sqlBuf =\r
+        new StringBuffer("insert into ").append(theTable).append("(").append(f)\r
+                                        .append(") values (").append(v).append(")");\r
       String sql = sqlBuf.toString();\r
-      //theLog.printInfo("INSERT: " + sql);\r
+\r
+      logger.debug("INSERT: " + sql);\r
       con = getPooledCon();\r
       con.setAutoCommit(false);\r
       pstmt = con.prepareStatement(sql);\r
+\r
       if (streamedInput != null) {\r
         for (int i = 0; i < streamedInput.size(); i++) {\r
-          String inputString = (String)theEntity.getValue((String)streamedInput.get(i));\r
+          String inputString =\r
+            (String) theEntity.getValue((String) streamedInput.get(i));\r
           pstmt.setBytes(i + 1, inputString.getBytes());\r
         }\r
       }\r
+\r
       int ret = pstmt.executeUpdate();\r
-      if(ret == 0){\r
+\r
+      if (ret == 0) {\r
         //insert failed\r
         return null;\r
       }\r
-      pstmt = con.prepareStatement(theAdaptor.getLastInsertSQL((Database)myselfDatabase));\r
+\r
+      pstmt = con.prepareStatement("select currval('" + getCoreTable() + "_id_seq')");\r
+\r
       ResultSet rs = pstmt.executeQuery();\r
       rs.next();\r
       returnId = rs.getString(1);\r
       theEntity.setId(returnId);\r
-    } catch (SQLException sqe) {\r
+    }\r
+    catch (SQLException sqe) {\r
       throwSQLException(sqe, "insert");\r
-    } finally {\r
+    }\r
+    finally {\r
       try {\r
         con.setAutoCommit(true);\r
-      } catch (Exception e) {\r
-        ;\r
       }\r
+      catch (Exception e) {\r
+      }\r
+\r
       freeConnection(con, pstmt);\r
     }\r
+\r
     /** @todo store entity in o_store */\r
-    return  returnId;\r
+    return returnId;\r
   }\r
 \r
   /**\r
-   * update-Operator: aktualisiert eine Entity. Eine Spalte WEBDB_LASTCHANGE\r
-   * wird automatisch mit dem aktuellen Datum gefuellt.\r
+   * Updates an entity in the database\r
    *\r
    * @param theEntity\r
    */\r
-  public void update (Entity theEntity) throws StorageObjectException\r
-  {\r
-    Connection con = null; PreparedStatement pstmt = null;\r
+  public void update(Entity theEntity) throws StorageObjectFailure {\r
+    Connection con = null;\r
+    PreparedStatement pstmt = null;\r
+\r
     /** @todo this is stupid: why do we prepare statement, when we\r
      *  throw it away afterwards. should be regular statement\r
      *  update/insert could better be one routine called save()\r
      *  that chooses to either insert or update depending if we\r
      *  have a primary key in the entity. i don't know if we\r
      *  still need the streamed input fields. // rk  */\r
-\r
     /** @todo extension: check if Entity did change, otherwise we don't need\r
      *  the roundtrip to the database */\r
-\r
     /** invalidating corresponding entitylists in o_store*/\r
-    if ( StoreUtil.implementsStorableObject(theEntityClass) ) {\r
+    if (StoreUtil.implementsStorableObject(theEntityClass)) {\r
       StoreContainerType stoc_type =\r
-          StoreContainerType.valueOf( theEntityClass,\r
+        StoreContainerType.valueOf(theEntityClass,\r
           StoreContainerType.STOC_TYPE_ENTITYLIST);\r
       o_store.invalidate(stoc_type);\r
     }\r
 \r
-    ArrayList streamedInput = theEntity.streamedInput();\r
+    List streamedInput = theEntity.streamedInput();\r
     String id = theEntity.getId();\r
     String aField;\r
     StringBuffer fv = new StringBuffer();\r
     boolean firstField = true;\r
+\r
     //cache\r
     invalidatePopupCache();\r
+\r
     // build sql statement\r
     for (int i = 0; i < getFields().size(); i++) {\r
-      aField = (String)metadataFields.get(i);\r
+      aField = (String) metadataFields.get(i);\r
+\r
       // only normal cases\r
-      if (!(aField.equals(thePKeyName) || aField.equals("webdb_create") ||\r
-            aField.equals("webdb_lastchange") || (streamedInput != null && streamedInput.contains(aField)))) {\r
+      if (  !(aField.equals(thePKeyName) ||\r
+            aField.equals("webdb_create") ||\r
+            aField.equals("webdb_lastchange") ||\r
+            ((streamedInput != null) && streamedInput.contains(aField)))) {\r
         if (theEntity.hasValueForField(aField)) {\r
           if (firstField == false) {\r
             fv.append(", ");\r
@@ -801,17 +937,22 @@ public class Database implements StorageObject {
           else {\r
             firstField = false;\r
           }\r
+\r
           fv.append(aField).append("='").append(JDBCStringRoutines.escapeStringLiteral((String) theEntity.getValue(aField))).append("'");\r
 \r
-//              fv.append(aField).append("='").append(StringUtil.quote((String)theEntity.getValue(aField))).append("'");\r
+          //              fv.append(aField).append("='").append(StringUtil.quote((String)theEntity.getValue(aField))).append("'");\r
         }\r
       }\r
     }\r
-    StringBuffer sql = new StringBuffer("update ").append(theTable).append(" set ").append(fv);\r
+\r
+    StringBuffer sql =\r
+      new StringBuffer("update ").append(theTable).append(" set ").append(fv);\r
+\r
     // exceptions\r
     if (metadataFields.contains("webdb_lastchange")) {\r
       sql.append(",webdb_lastchange=NOW()");\r
     }\r
+\r
     // special case: the webdb_create requires the field in yyyy-mm-dd HH:mm\r
     // format so anything extra will be ignored. -mh\r
     if (metadataFields.contains("webdb_create") &&\r
@@ -819,38 +960,46 @@ public class Database implements StorageObject {
       // minimum of 10 (yyyy-mm-dd)...\r
       if (theEntity.getValue("webdb_create").length() >= 10) {\r
         String dateString = theEntity.getValue("webdb_create");\r
+\r
         // if only 10, then add 00:00 so it doesn't throw a ParseException\r
-        if (dateString.length() == 10)\r
-          dateString=dateString+" 00:00";\r
+        if (dateString.length() == 10) {\r
+          dateString = dateString + " 00:00";\r
+        }\r
 \r
         // TimeStamp stuff\r
         try {\r
-          java.util.Date d = _dateFormatterIn.parse(dateString);\r
-          Timestamp tStamp = new Timestamp(d.getTime());\r
-          sql.append(",webdb_create='"+tStamp.toString()+"'");\r
-        } catch (ParseException e) {\r
-          throw new StorageObjectException(e.getMessage());\r
+          java.util.Date d = userInputDateFormat.parse(dateString);\r
+//          Timestamp tStamp = new Timestamp(d.getTime());\r
+          sql.append(",webdb_create='" + JDBCStringRoutines.formatDate(d) + "'");\r
+        }\r
+        catch (ParseException e) {\r
+          throw new StorageObjectFailure(e);\r
         }\r
       }\r
     }\r
+\r
     if (streamedInput != null) {\r
       for (int i = 0; i < streamedInput.size(); i++) {\r
         sql.append(",").append(streamedInput.get(i)).append("=?");\r
       }\r
     }\r
+\r
     sql.append(" where id=").append(id);\r
-    //theLog.printInfo("UPDATE: " + sql);\r
-    // execute sql\r
+    logger.debug("UPDATE: " + sql);\r
+\r
     try {\r
       con = getPooledCon();\r
       con.setAutoCommit(false);\r
       pstmt = con.prepareStatement(sql.toString());\r
+\r
       if (streamedInput != null) {\r
         for (int i = 0; i < streamedInput.size(); i++) {\r
-          String inputString = theEntity.getValue((String)streamedInput.get(i));\r
+          String inputString =\r
+            theEntity.getValue((String) streamedInput.get(i));\r
           pstmt.setBytes(i + 1, inputString.getBytes());\r
         }\r
       }\r
+\r
       pstmt.executeUpdate();\r
     }\r
     catch (SQLException sqe) {\r
@@ -859,175 +1008,108 @@ public class Database implements StorageObject {
     finally {\r
       try {\r
         con.setAutoCommit(true);\r
-      } catch (Exception e) {\r
+      }\r
+      catch (Exception e) {\r
         ;\r
       }\r
+\r
       freeConnection(con, pstmt);\r
     }\r
   }\r
 \r
-      /*\r
+  /*\r
   *   delete-Operator\r
   *   @param id des zu loeschenden Datensatzes\r
   *   @return boolean liefert true zurueck, wenn loeschen erfolgreich war.\r
-       */\r
-  public boolean delete (String id) throws StorageObjectException {\r
-\r
+   */\r
+  public boolean delete(String id) throws StorageObjectFailure {\r
     invalidatePopupCache();\r
+\r
     // ostore send notification\r
-    if ( StoreUtil.implementsStorableObject(theEntityClass) ) {\r
+    if (StoreUtil.implementsStorableObject(theEntityClass)) {\r
       String uniqueId = id;\r
-      if ( theEntityClass.equals(StorableObjectEntity.class) )\r
-        uniqueId+="@"+theTable;\r
-      theLog.printInfo("CACHE: (del) " + id);\r
+\r
+      if (theEntityClass.equals(StorableObjectEntity.class)) {\r
+        uniqueId += ("@" + theTable);\r
+      }\r
+\r
+      logger.debug("CACHE: (del) " + id);\r
+\r
       StoreIdentifier search_sid =\r
-          new StoreIdentifier(theEntityClass, StoreContainerType.STOC_TYPE_ENTITY, uniqueId);\r
+        new StoreIdentifier(theEntityClass,\r
+          StoreContainerType.STOC_TYPE_ENTITY, uniqueId);\r
       o_store.invalidate(search_sid);\r
     }\r
 \r
     /** @todo could be prepared Statement */\r
-    Statement stmt = null; Connection con = null;\r
+    Statement stmt = null;\r
+    Connection con = null;\r
     int res = 0;\r
-    String sql="delete from "+theTable+" where "+thePKeyName+"='"+id+"'";\r
+    String sql =\r
+      "delete from " + theTable + " where " + thePKeyName + "='" + id + "'";\r
+\r
     //theLog.printInfo("DELETE " + sql);\r
     try {\r
-      con = getPooledCon(); stmt = con.createStatement();\r
+      con = getPooledCon();\r
+      stmt = con.createStatement();\r
       res = stmt.executeUpdate(sql);\r
+    } catch (SQLException sqe) {\r
+      throwSQLException(sqe, "delete");\r
+    } finally {\r
+      freeConnection(con, stmt);\r
     }\r
-    catch (SQLException sqe) { throwSQLException(sqe, "delete"); }\r
-    finally { freeConnection(con, stmt); }\r
 \r
-    return  (res > 0) ? true : false;\r
-  }\r
-\r
-      /* noch nicht implementiert.\r
-  * @return immer false\r
-       */\r
-  public boolean delete (EntityList theEntityList) {\r
-    invalidatePopupCache();\r
-    return  false;\r
+    return (res > 0) ? true : false;\r
   }\r
 \r
   /**\r
-   * Diese Methode sollte ueberschrieben werden, wenn fuer die abgeleitete Database-Klasse\r
-   * eine SimpleList mit Standard-Popupdaten erzeugt werden koennen soll.\r
-   * @return null\r
-   */\r
-  public SimpleList getPopupData () throws StorageObjectException {\r
-    return  null;\r
-  }\r
-\r
-  /**\r
-   *  Holt Daten fuer Popups.\r
-   *  @param name  Name des Feldes.\r
-   *  @param hasNullValue  Wenn true wird eine leerer  Eintrag fuer die Popups erzeugt.\r
-   *  @return SimpleList Gibt freemarker.template.SimpleList zurueck.\r
-   */\r
-  public SimpleList getPopupData (String name, boolean hasNullValue)\r
-      throws StorageObjectException {\r
-    return  getPopupData(name, hasNullValue, null);\r
-  }\r
-\r
-  /**\r
-   *  Holt Daten fuer Popups.\r
-   *  @param name  Name des Feldes.\r
-   *  @param hasNullValue  Wenn true wird eine leerer  Eintrag fuer die Popups erzeugt.\r
-   *  @param where  Schraenkt die Selektion der Datensaetze ein.\r
-   *  @return SimpleList Gibt freemarker.template.SimpleList zurueck.\r
+   * Deletes entities based on a where clause\r
+   *\r
+   * @param aWhereClause\r
+   * @return\r
+   * @throws StorageObjectFailure\r
    */\r
-  public SimpleList getPopupData (String name, boolean hasNullValue, String where) throws StorageObjectException {\r
-    return  getPopupData(name, hasNullValue, where, null);\r
-  }\r
+  public int deleteByWhereClause(String aWhereClause) throws StorageObjectFailure {\r
+    invalidatePopupCache();\r
+    if (StoreUtil.implementsStorableObject(theEntityClass)) {\r
+      StoreContainerType stoc_type = StoreContainerType.valueOf(theEntityClass, StoreContainerType.STOC_TYPE_ENTITYLIST);\r
+      o_store.invalidate(stoc_type);\r
+    }\r
 \r
-  /**\r
-   *  Holt Daten fuer Popups.\r
-   *  @param name  Name des Feldes.\r
-   *  @param hasNullValue  Wenn true wird eine leerer  Eintrag fuer die Popups erzeugt.\r
-   *  @param where  Schraenkt die Selektion der Datensaetze ein.\r
-   *  @param order  Gibt ein Feld als Sortierkriterium an.\r
-   *  @return SimpleList Gibt freemarker.template.SimpleList zurueck.\r
-   */\r
-  public SimpleList getPopupData (String name, boolean hasNullValue, String where, String order) throws StorageObjectException {\r
-    // caching\r
-    if (hasPopupCache && popupCache != null)\r
-      return  popupCache;\r
-    SimpleList simpleList = null;\r
-    Connection con = null;\r
     Statement stmt = null;\r
-    // build sql\r
-    StringBuffer sql = new StringBuffer("select ").append(thePKeyName)\r
-                     .append(",").append(name).append(" from ")\r
-                     .append(theTable);\r
-    if (where != null && !(where.length() == 0))\r
-      sql.append(" where ").append(where);\r
-    sql.append(" order by ");\r
-    if (order != null && !(order.length() == 0))\r
-      sql.append(order);\r
-    else\r
-      sql.append(name);\r
-    // execute sql\r
+    Connection con = null;\r
+    int res = 0;\r
+    String sql =\r
+      "delete from " + theTable + " where " + aWhereClause;\r
+\r
+    //theLog.printInfo("DELETE " + sql);\r
     try {\r
       con = getPooledCon();\r
-    }\r
-    catch (Exception e) {\r
-      throw new StorageObjectException(e.getMessage());\r
-    }\r
-    try {\r
       stmt = con.createStatement();\r
-      ResultSet rs = executeSql(stmt, sql.toString());\r
-\r
-      if (rs != null) {\r
-        if (!evaluatedMetaData) get_meta_data();\r
-        simpleList = new SimpleList();\r
-        // if popup has null-selector\r
-        if (hasNullValue) simpleList.add(POPUP_EMTYLINE);\r
-\r
-        SimpleHash popupDict;\r
-        while (rs.next()) {\r
-          popupDict = new SimpleHash();\r
-          popupDict.put("key", getValueAsString(rs, 1, thePKeyType));\r
-          popupDict.put("value", rs.getString(2));\r
-          simpleList.add(popupDict);\r
-        }\r
-        rs.close();\r
-      }\r
+      res = stmt.executeUpdate(sql);\r
     }\r
-    catch (Exception e) {\r
-      theLog.printError("getPopupData: "+e.getMessage());\r
-      throw new StorageObjectException(e.toString());\r
+    catch (SQLException sqe) {\r
+      throwSQLException(sqe, "delete");\r
     }\r
     finally {\r
       freeConnection(con, stmt);\r
     }\r
 \r
-    if (hasPopupCache) popupCache = simpleList;\r
-    return  simpleList;\r
+    return res;\r
   }\r
 \r
-  /**\r
-   * Liefert alle Daten der Tabelle als SimpleHash zurueck. Dies wird verwandt,\r
-   * wenn in den Templates ein Lookup-Table benoetigt wird. Sollte nur bei kleinen\r
-   * Tabellen Verwendung finden.\r
-   * @return SimpleHash mit den Tabellezeilen.\r
+  /* noch nicht implementiert.\r
+  * @return immer false\r
    */\r
-  public SimpleHash getHashData () {\r
-    /** @todo dangerous! this should have a flag to be enabled, otherwise\r
-     *  very big Hashes could be returned */\r
-    if (hashCache == null) {\r
-      try {\r
-        hashCache = HTMLTemplateProcessor.makeSimpleHash(selectByWhereClause("",\r
-            -1));\r
-      }\r
-      catch (StorageObjectException e) {\r
-        theLog.printDebugInfo(e.getMessage());\r
-      }\r
-    }\r
-    return  hashCache;\r
+  public boolean delete(EntityList theEntityList) {\r
+    invalidatePopupCache();\r
+\r
+    return false;\r
   }\r
 \r
-      /* invalidates the popupCache\r
-       */\r
-  protected void invalidatePopupCache () {\r
+  /* invalidates the popupCache\r
+   */\r
+  protected void invalidatePopupCache() {\r
     /** @todo  invalidates toooo much */\r
     popupCache = null;\r
     hashCache = null;\r
@@ -1040,50 +1122,136 @@ public class Database implements StorageObject {
    * @return ResultSet\r
    * @exception StorageObjectException\r
    */\r
-  public ResultSet executeSql (Statement stmt, String sql)\r
-      throws StorageObjectException, SQLException\r
-  {\r
-    long startTime = System.currentTimeMillis();\r
+  public ResultSet executeSql(Statement stmt, String sql)\r
+                            throws StorageObjectFailure, SQLException {\r
     ResultSet rs;\r
+    long startTime = System.currentTimeMillis();\r
+\r
     try {\r
       rs = stmt.executeQuery(sql);\r
-      //theLog.printInfo((System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
+\r
+      logger.debug((System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
     }\r
-    catch (SQLException e)\r
-    {\r
-      theLog.printDebugInfo("Failed: " + (System.currentTimeMillis() - startTime) + "ms. for: "+ sql);\r
+    catch (SQLException e) {\r
+      logger.error(e.getMessage() +"\n" + (System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
       throw e;\r
     }\r
 \r
-    return  rs;\r
+    return rs;\r
   }\r
+/*\r
+  public ResultSet executeSql(String sql) throws StorageObjectFailure, SQLException {\r
+    long startTime = System.currentTimeMillis();\r
+    Connection connection = null;\r
+    Statement statement = null;\r
 \r
-  /**\r
-   * Fuehrt Statement stmt aus und liefert Resultset zurueck. Das SQL-Statment wird\r
-   * getimed und geloggt.\r
-   * @param stmt PreparedStatement mit der SQL-Anweisung\r
-   * @return Liefert ResultSet des Statements zurueck.\r
-   * @exception StorageObjectException, SQLException\r
-   */\r
-  public ResultSet executeSql (PreparedStatement stmt)\r
-      throws StorageObjectException, SQLException {\r
+    try {\r
+      connection = getPooledCon();\r
+      statement = connection.createStatement();\r
+      ResultSet result;\r
 \r
-    long startTime = (new java.util.Date()).getTime();\r
-    ResultSet rs = stmt.executeQuery();\r
-    theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms.");\r
-    return  rs;\r
+      result = statement.executeQuery(sql);\r
+\r
+      logger.debug((System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
+      return result;\r
+    }\r
+    catch (Throwable e) {\r
+      logger.error(e.getMessage() +"\n" + (System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
+      throw new StorageObjectFailure(e);\r
+    }\r
+    finally {\r
+      if (connection!=null) {\r
+        freeConnection(connection, statement);\r
+      }\r
+    }\r
   }\r
+*/\r
+  private Map processRow(ResultSet aResultSet) throws StorageObjectFailure, StorageObjectExc {\r
+    try {\r
+      Map result = new HashMap();\r
+      ResultSetMetaData metaData = aResultSet.getMetaData();\r
+      int nrColumns = metaData.getColumnCount();\r
+      for (int i=0; i<nrColumns; i++) {\r
+        result.put(metaData.getColumnName(i+1), getValueAsString(aResultSet, i+1, metaData.getColumnType(i+1)));\r
+      }\r
+\r
+      return result;\r
+    }\r
+    catch (Throwable e) {\r
+      throw new StorageObjectFailure(e);\r
+    }\r
+  }\r
+\r
+  public List executeFreeSql(String sql, int aLimit) throws StorageObjectFailure, StorageObjectExc {\r
+    Connection connection = null;\r
+    Statement statement = null;\r
+    try {\r
+      List result = new Vector();\r
+      connection = getPooledCon();\r
+      statement = connection.createStatement();\r
+      ResultSet resultset = executeSql(statement, sql);\r
+      try {\r
+        while (resultset.next() && result.size() < aLimit) {\r
+          result.add(processRow(resultset));\r
+        }\r
+      }\r
+      finally {\r
+        resultset.close();\r
+      }\r
+\r
+      return result;\r
+    }\r
+    catch (Throwable e) {\r
+      throw new StorageObjectFailure(e);\r
+    }\r
+    finally {\r
+      if (connection!=null) {\r
+        freeConnection(connection, statement);\r
+      }\r
+    }\r
+  };\r
+\r
+  public Map executeFreeSingleRowSql(String anSqlStatement) throws StorageObjectFailure, StorageObjectExc {\r
+    try {\r
+      List resultList = executeFreeSql(anSqlStatement, 1);\r
+      try {\r
+        if (resultList.size()>0)\r
+          return (Map) resultList.get(0);\r
+        else\r
+          return null;\r
+      }\r
+      finally {\r
+      }\r
+    }\r
+    catch (Throwable t) {\r
+      throw new StorageObjectFailure(t);\r
+    }\r
+  };\r
+\r
+  public String executeFreeSingleValueSql(String sql) throws StorageObjectFailure, StorageObjectExc {\r
+    Map row = executeFreeSingleRowSql(sql);\r
+\r
+    if (row==null)\r
+      return null;\r
+\r
+    Iterator i = row.values().iterator();\r
+    if (i.hasNext())\r
+      return (String) i.next();\r
+    else\r
+      return null;\r
+  };\r
 \r
   /**\r
    * returns the number of rows in the table\r
    */\r
-  public int getSize(String where)\r
-      throws SQLException,StorageObjectException\r
-  {\r
-    long  startTime = System.currentTimeMillis();\r
-    String sql = "SELECT Count(*) FROM "+ theTable;\r
-    if (where != null && !(where.length() == 0))\r
+  public int getSize(String where) throws SQLException, StorageObjectFailure {\r
+    long startTime = System.currentTimeMillis();\r
+    String sql = "SELECT Count(*) FROM " + theTable;\r
+\r
+    if ((where != null) && (where.length() != 0)) {\r
       sql = sql + " where " + where;\r
+    }\r
+\r
     Connection con = null;\r
     Statement stmt = null;\r
     int result = 0;\r
@@ -1091,60 +1259,65 @@ public class Database implements StorageObject {
     try {\r
       con = getPooledCon();\r
       stmt = con.createStatement();\r
-      ResultSet rs = executeSql(stmt,sql);\r
-      while(rs.next()){\r
+\r
+      ResultSet rs = executeSql(stmt, sql);\r
+\r
+      while (rs.next()) {\r
         result = rs.getInt(1);\r
       }\r
     }\r
     catch (SQLException e) {\r
-      theLog.printError(e.getMessage());\r
+      logger.error("Database.getSize: " + e.getMessage());\r
     }\r
     finally {\r
-      freeConnection(con,stmt);\r
+      freeConnection(con, stmt);\r
     }\r
+\r
     //theLog.printInfo(theTable + " has "+ result +" rows where " + where);\r
-    //theLog.printInfo((System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
+    logger.debug((System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
+\r
     return result;\r
   }\r
 \r
   public int executeUpdate(Statement stmt, String sql)\r
-      throws StorageObjectException, SQLException\r
-  {\r
+    throws StorageObjectFailure, SQLException {\r
     int rs;\r
-    long  startTime = (new java.util.Date()).getTime();\r
-    try\r
-    {\r
+    long startTime = System.currentTimeMillis();\r
+\r
+    try {\r
       rs = stmt.executeUpdate(sql);\r
-      //theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: " + sql);\r
+\r
+      logger.debug((System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
     }\r
-    catch (SQLException e)\r
-    {\r
-      theLog.printDebugInfo("Failed: " + (new java.util.Date().getTime()\r
-          - startTime) + "ms. for: "+ sql);\r
+    catch (SQLException e) {\r
+      logger.error("Failed: " + (System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
       throw e;\r
     }\r
+\r
     return rs;\r
   }\r
 \r
-  public int executeUpdate(String sql) throws StorageObjectException, SQLException\r
-  {\r
-    int result=-1;\r
-    long  startTime = (new java.util.Date()).getTime();\r
-    Connection con=null;\r
-    PreparedStatement pstmt=null;\r
+  public int executeUpdate(String sql)\r
+    throws StorageObjectFailure, SQLException {\r
+    int result = -1;\r
+    long startTime = System.currentTimeMillis();\r
+    Connection con = null;\r
+    PreparedStatement pstmt = null;\r
+\r
     try {\r
-      con=getPooledCon();\r
+      con = getPooledCon();\r
       pstmt = con.prepareStatement(sql);\r
       result = pstmt.executeUpdate();\r
     }\r
-    catch (Exception e) {\r
-      theLog.printDebugInfo("executeUpdate failed: "+e.getMessage());\r
-      throw new StorageObjectException("executeUpdate failed: "+e.getMessage());\r
+    catch (Throwable e) {\r
+      logger.error("Database.executeUpdate(" + sql + "): " + e.getMessage());\r
+      throw new StorageObjectFailure("Database.executeUpdate(" + sql + "): " + e.getMessage(), e);\r
     }\r
     finally {\r
-      freeConnection(con,pstmt);\r
+      freeConnection(con, pstmt);\r
     }\r
-    //theLog.printInfo((new java.util.Date().getTime() - startTime) + "ms. for: " + sql);\r
+\r
+    logger.debug((System.currentTimeMillis() - startTime) + "ms. for: " + sql);\r
     return result;\r
   }\r
 \r
@@ -1153,32 +1326,37 @@ public class Database implements StorageObject {
    * @param md ResultSetMetaData\r
    * @exception StorageObjectException\r
    */\r
-  private void evalMetaData (ResultSetMetaData md)\r
-      throws StorageObjectException {\r
-\r
+  private void evalMetaData(ResultSetMetaData md) throws StorageObjectFailure {\r
     this.evaluatedMetaData = true;\r
     this.metadataFields = new ArrayList();\r
     this.metadataLabels = new ArrayList();\r
     this.metadataNotNullFields = new ArrayList();\r
+\r
     try {\r
       int numFields = md.getColumnCount();\r
       this.metadataTypes = new int[numFields];\r
+\r
       String aField;\r
       int aType;\r
+\r
       for (int i = 1; i <= numFields; i++) {\r
         aField = md.getColumnName(i);\r
         metadataFields.add(aField);\r
         metadataLabels.add(md.getColumnLabel(i));\r
         aType = md.getColumnType(i);\r
         metadataTypes[i - 1] = aType;\r
+\r
         if (aField.equals(thePKeyName)) {\r
-          thePKeyType = aType; thePKeyIndex = i;\r
+          thePKeyType = aType;\r
+          thePKeyIndex = i;\r
         }\r
-        if (md.isNullable(i) == md.columnNullable) {\r
+\r
+        if (md.isNullable(i) == ResultSetMetaData.columnNullable) {\r
           metadataNotNullFields.add(aField);\r
         }\r
       }\r
-    } catch (SQLException e) {\r
+    }\r
+    catch (SQLException e) {\r
       throwSQLException(e, "evalMetaData");\r
     }\r
   }\r
@@ -1187,49 +1365,46 @@ public class Database implements StorageObject {
    *  Wertet die Metadaten eines Resultsets fuer eine Tabelle aus,\r
    *  um die alle Columns und Typen einer Tabelle zu ermitteln.\r
    */\r
-  private void get_meta_data () throws StorageObjectException {\r
+  private void get_meta_data() throws StorageObjectFailure {\r
     Connection con = null;\r
     PreparedStatement pstmt = null;\r
     String sql = "select * from " + theTable + " where 0=1";\r
+\r
     try {\r
       con = getPooledCon();\r
       pstmt = con.prepareStatement(sql);\r
-      //theLog.printInfo("METADATA: " + sql);\r
+\r
+      logger.debug("METADATA: " + sql);\r
       ResultSet rs = pstmt.executeQuery();\r
       evalMetaData(rs.getMetaData());\r
       rs.close();\r
-    } catch (SQLException e) {\r
+    }\r
+    catch (SQLException e) {\r
       throwSQLException(e, "get_meta_data");\r
-    } finally {\r
+    }\r
+    finally {\r
       freeConnection(con, pstmt);\r
     }\r
   }\r
 \r
-\r
-  public Connection getPooledCon() throws StorageObjectException {\r
-              /* @todo , doublecheck but I'm pretty sure that this is unnecessary. -mh\r
-                      try{\r
-                      Class.forName("com.codestudio.sql.PoolMan").newInstance();\r
-              } catch (Exception e){\r
-                      throw new StorageObjectException("Could not find the PoolMan Driver"\r
-                          +e.toString());\r
-              }*/\r
+  public Connection getPooledCon() throws StorageObjectFailure {\r
     Connection con = null;\r
 \r
-    try{\r
+    try {\r
       con = SQLManager.getInstance().requestConnection();\r
     }\r
-    catch(SQLException e){\r
-      theLog.printError("could not connect to the database "+e.getMessage());\r
-      System.err.println("could not connect to the database "+e.getMessage());\r
-      throw new StorageObjectException("Could not connect to the database"+ e.getMessage());\r
+    catch (SQLException e) {\r
+      logger.error("could not connect to the database " + e.getMessage());\r
+\r
+      throw new StorageObjectFailure("Could not connect to the database", e);\r
     }\r
 \r
     return con;\r
   }\r
 \r
-  public void freeConnection (Connection con, Statement stmt) throws StorageObjectException {\r
-    SQLManager.getInstance().closeStatement(stmt);\r
+  public void freeConnection(Connection con, Statement stmt)\r
+    throws StorageObjectFailure {\r
+    SQLManager.closeStatement(stmt);\r
     SQLManager.getInstance().returnConnection(con);\r
   }\r
 \r
@@ -1239,33 +1414,36 @@ public class Database implements StorageObject {
    * @param wo Funktonsname, in der die SQLException geworfen wurde\r
    * @exception StorageObjectException\r
    */\r
-  protected void throwSQLException (SQLException sqe, String wo) throws StorageObjectException {\r
+  protected void throwSQLException(SQLException sqe, String aFunction) throws StorageObjectFailure {\r
     String state = "";\r
     String message = "";\r
     int vendor = 0;\r
+\r
     if (sqe != null) {\r
       state = sqe.getSQLState();\r
       message = sqe.getMessage();\r
       vendor = sqe.getErrorCode();\r
     }\r
-    theLog.printError(state + ": " + vendor + " : " + message + " Funktion: "\r
-                      + wo);\r
-    throw new StorageObjectException((sqe == null) ? "undefined sql exception" :\r
-                                      sqe.getMessage());\r
+\r
+    String information =\r
+        "SQL Error: " +\r
+        "state= " + state +\r
+        ", vendor= " + vendor +\r
+        ", message=" + message +\r
+        ", function= " + aFunction;\r
+\r
+    logger.error(information);\r
+\r
+    throw new StorageObjectFailure(information, sqe);\r
   }\r
 \r
-  protected void _throwStorageObjectException (Exception e, String wo)\r
-      throws StorageObjectException {\r
+  protected void _throwStorageObjectException(Exception e, String aFunction)\r
+    throws StorageObjectFailure {\r
 \r
     if (e != null) {\r
-      theLog.printError(e.getMessage()+ wo);\r
-      throw  new StorageObjectException(wo + e.getMessage());\r
-    }\r
-    else {\r
-      theLog.printError(wo);\r
-      throw  new StorageObjectException(wo);\r
+      logger.error(e.getMessage() + aFunction);\r
+      throw new StorageObjectFailure(aFunction, e);\r
     }\r
-\r
   }\r
 \r
   /**\r
@@ -1274,12 +1452,8 @@ public class Database implements StorageObject {
    * @param message Nachricht mit dem Fehler\r
    * @exception StorageObjectException\r
    */\r
-  void throwStorageObjectException (String message)\r
-      throws StorageObjectException {\r
-    _throwStorageObjectException(null, message);\r
+  void throwStorageObjectException(String aMessage) throws StorageObjectFailure {\r
+    logger.error(aMessage);\r
+    throw new StorageObjectFailure(aMessage, null);\r
   }\r
-\r
-}\r
-\r
-\r
-\r
+}