producer abort + timezone support
authorzapata <zapata>
Mon, 23 Jun 2003 15:24:06 +0000 (15:24 +0000)
committerzapata <zapata>
Mon, 23 Jun 2003 15:24:06 +0000 (15:24 +0000)
23 files changed:
bundles/admin_en.properties
source/default.properties
source/mir/entity/adapter/EntityAdapterDefinition.java
source/mir/misc/StringUtil.java
source/mir/producer/NodedProducer.java
source/mir/producer/Producer.java
source/mir/servlet/ServletModule.java
source/mir/storage/Database.java
source/mir/util/DateToMapAdapter.java [deleted file]
source/mir/util/GeneratorFormatAdapters.java
source/mir/util/HTTPRequestParser.java
source/mir/util/JDBCStringRoutines.java
source/mircoders/global/Abuse.java
source/mircoders/global/JobQueue.java
source/mircoders/global/ProducerEngine.java
source/mircoders/localizer/basic/MirBasicDataModelLocalizer.java
source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java
source/mircoders/servlet/ServletHelper.java
source/mircoders/servlet/ServletModuleProducer.java
templates/admin/abuse.log.template
templates/admin/content.template
templates/admin/producerqueue.template
web/style/admin.css

index a17f56e..3c20519 100755 (executable)
@@ -1,6 +1,6 @@
 ########## admin ##########
 # language: english
-# $Id: admin_en.properties,v 1.48.2.2 2003/06/21 04:02:08 zapata Exp $
+# $Id: admin_en.properties,v 1.48.2.3 2003/06/23 15:24:06 zapata Exp $
 
 languagename=English
 
@@ -389,6 +389,7 @@ producer.job.abort = abort
 producer.job.empty = Queue is empty
 producer.job.runningtime = Running time
 
+producer.jobqueue.canceljobs = Cancel selected jobs
 producer.jobqueue.title = Current jobs
 producer.jobqueue.refresh = refresh
 producer.producerlist.title = Add a new job
index 8a2f18c..b5487bb 100755 (executable)
@@ -388,6 +388,11 @@ Mir.DefaultEncoding=UTF8
 # don't change this unless...
 Mir.DefaultHTMLCharset=UTF-8
 
+# Default timezone to display times in in admin, producers
+# 
+# Leave empty to use the system's default
+Mir.DefaultTimezone= 
+
 
 
 
index 8162bb9..bb132a5 100755 (executable)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
  * If you do not wish to do so, delete this exception statement from your version.
  */
 package mir.entity.adapter;
@@ -32,11 +32,12 @@ package mir.entity.adapter;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
-import java.util.HashMap;
+import java.util.*;
 import java.util.Map;
 
 import mir.entity.Entity;
-import mir.util.DateToMapAdapter;
+import mir.util.GeneratorFormatAdapters;
+import mir.misc.*;
 
 public class EntityAdapterDefinition {
   Map calculatedFields;
@@ -61,12 +62,12 @@ public class EntityAdapterDefinition {
     calculatedFields.put(aFieldName, aField);
   }
 
-  public void addMirDateField(String aDestinationFieldName, String aSourceFieldName) {
-    addCalculatedField(aDestinationFieldName, new MirDateField(aSourceFieldName));
+  public void addMirDateField(String aDestinationFieldName, String aSourceFieldName, String aDefaultTimezone) {
+    addCalculatedField(aDestinationFieldName, new MirDateField(aSourceFieldName, aDefaultTimezone));
   }
 
-  public void addDBDateField(String aDestinationFieldName, String aSourceFieldName) {
-    addCalculatedField(aDestinationFieldName, new DBDateField(aSourceFieldName));
+  public void addDBDateField(String aDestinationFieldName, String aSourceFieldName, String aDefaultTimezone) {
+    addCalculatedField(aDestinationFieldName, new DBDateField(aSourceFieldName, aDefaultTimezone));
   }
 
   public interface CalculatedField {
@@ -75,80 +76,62 @@ public class EntityAdapterDefinition {
 
   private class MirDateField implements CalculatedField {
     private String fieldName;
+    private String defaultTimezone;
 
-    public MirDateField(String aFieldName) {
+    public MirDateField(String aFieldName, String aDefaultTimezone) {
       fieldName = aFieldName;
+      defaultTimezone = aDefaultTimezone;
     }
 
     public Object getValue(EntityAdapter anEntityAdapter) {
 
-      Map result = new HashMap();
-      String textValue = anEntityAdapter.getEntity().getValue(fieldName);
-      Calendar calendar = GregorianCalendar.getInstance();
-      int year;
-      int month;
-      int day;
-      Date date;
-
-      if (textValue!=null) {
-        try {
-          year = Integer.parseInt(textValue.substring(0,4));
-          month = Integer.parseInt(textValue.substring(4,6));
-          day = Integer.parseInt(textValue.substring(6,8));
-
-          calendar.set(year, month-1, day);
-          date = calendar.getTime();
-          ;
-
-          result.put("date", date);
-          result.put("formatted", new DateToMapAdapter(date));
-
-        }
-        catch (Throwable t) {
-          result=null;
-        }
-      }
-      return result;
-    }
+         Object result = null;
+         String textValue = anEntityAdapter.getEntity().getValue(fieldName);
+         Calendar calendar = GregorianCalendar.getInstance();
+         int year;
+         int month;
+         int day;
+         Date date;
+
+         if (textValue!=null) {
+           try {
+             year = Integer.parseInt(textValue.substring(0,4));
+             month = Integer.parseInt(textValue.substring(4,6));
+             day = Integer.parseInt(textValue.substring(6,8));
+
+             calendar.setTimeZone(TimeZone.getTimeZone(defaultTimezone));
+             calendar.set(year, month-1, day);
+
+             date = calendar.getTime();
+
+             result = new GeneratorFormatAdapters.DateFormatAdapter(date, defaultTimezone);
+           }
+           catch (Throwable t) {
+             result=null;
+           }
+         }
+         return result;
+       }
   }
 
   private class DBDateField implements CalculatedField {
     private String fieldName;
+    private String defaultTimezone;
 
-    public DBDateField(String aFieldName) {
+    public DBDateField(String aFieldName, String aDefaultTimezone) {
       fieldName = aFieldName;
+      defaultTimezone = aDefaultTimezone;
     }
 
     public Object getValue(EntityAdapter anEntityAdapter) {
+      Object result = null;
+      String text = anEntityAdapter.getEntity().getValue(fieldName);
 
-      Map result = new HashMap();
-      String textValue = anEntityAdapter.getEntity().getValue(fieldName);
-      Calendar calendar = GregorianCalendar.getInstance();
-      int year;
-      int month;
-      int day;
-      int hours;
-      int minutes;
-
-      Date date;
-
-      if (textValue!=null) {
+      if (text!=null) {
         try {
-          year = Integer.parseInt(textValue.substring(0,4));
-          month = Integer.parseInt(textValue.substring(5,7));
-          day = Integer.parseInt(textValue.substring(8,10));
-          hours = Integer.parseInt(textValue.substring(11,13));
-          minutes = Integer.parseInt(textValue.substring(14,16));
-
-          calendar.set(year, month-1, day, hours, minutes);
-          date = calendar.getTime();
-
-          result.put("date", date);
-          result.put("formatted", new DateToMapAdapter(date));
-          result.put("raw", textValue);
+          result = new GeneratorFormatAdapters.DateFormatAdapter(StringUtil.convertMirInternalDateToDate(text), defaultTimezone);
         }
         catch (Throwable t) {
-          result=null;
         }
       }
 
index bb26ae7..3daf500 100755 (executable)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
  * If you do not wish to do so, delete this exception statement from your version.
  */
 package  mir.misc;
@@ -35,13 +35,13 @@ import gnu.regexp.REException;
 import java.io.File;
 import java.text.NumberFormat;
 import java.util.Calendar;
-import java.util.GregorianCalendar;
+import java.util.*;
 import java.util.StringTokenizer;
 
 /**
  * Statische Hilfsmethoden zur Stringbehandlung
  *
- * @version $Id: StringUtil.java,v 1.33 2003/04/21 12:42:52 idfx Exp $
+ * @version $Id: StringUtil.java,v 1.33.2.1 2003/06/23 15:24:06 zapata Exp $
  * @author mir-coders group
  *
  */
@@ -60,8 +60,8 @@ public final class StringUtil {
       re_mail       = new RE("([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_-]+)\\.([a-zA-Z0-9_.-]+)");
       re_url        = new RE("((https://)|(http://)|(ftp://)){1}([a-zA-Z0-9_-]+).([a-zA-Z0-9_.:-]+)/?([^ \t\r\n<>\\)\\]]+[^ \t\r\n.,<>\\)\\]])");
       re_tags       = new RE("<[^>]*>",RE.REG_ICASE);
-                       re_tables = new RE("<[ \t\r\n/]*(table|td|tr)[ \t\r\n]*>",RE.REG_ICASE);
-                       re_forbiddenTags = new RE("<[ \t\r\n/]*(body|head|script)[ \t\r\n]*>",RE.REG_ICASE);
+      re_tables = new RE("<[ \t\r\n/]*(table|td|tr)[ \t\r\n]*>",RE.REG_ICASE);
+      re_forbiddenTags = new RE("<[ \t\r\n/]*(body|head|script)[ \t\r\n]*>",RE.REG_ICASE);
     }
     catch (REException e){
       System.err.println("FATAL: StringUtil: could not precompile REGEX: "+e.toString());
@@ -169,10 +169,10 @@ public final class StringUtil {
     return re_forbiddenTags.substituteAll(haystack,"");
   }
 
-       /**
-        *  deleteHTMLTableTags
-        *  this method deletes all <table>, <tr> and <td>-tags
-        */
+  /**
+   *  deleteHTMLTableTags
+   *  this method deletes all <table>, <tr> and <td>-tags
+   */
   public static final String deleteHTMLTableTags(String haystack) {
     return re_tables.substituteAll(haystack,"");
   }
@@ -195,155 +195,6 @@ public final class StringUtil {
   }
 
   /**
-   * converts string from format: yyyy-mm-dd__hh:mm:ss.d
-   * to dd.mm.yyyy hh:mm
-   */
-  public static String dateToReadableDate(String date) {
-    StringBuffer returnDate = new StringBuffer();
-    if (date!=null) {
-
-      returnDate.append(date.substring(8,10)).append('.');
-      returnDate.append(date.substring(5,7)).append('.');
-      returnDate.append(date.substring(0,4)).append(' ');
-      returnDate.append(date.substring(11,16));
-    }
-    return returnDate.toString();
-  }
-
-  /**
-   * converts string from format: yyyy-mm-dd__hh:mm:ss.d
-   * to yyyy
-   */
-  public static String dateToYear (String date) {
-    StringBuffer returnDate = new StringBuffer();
-    if (date!=null) {
-
-      returnDate.append(date.substring(0,4));
-    }
-    return returnDate.toString();
-  }
-
-  /**
-   * converts string from format: yyyy-mm-dd__hh:mm:ss.d
-   * to [m]m
-   */
-  public static String dateToMonth (String date) {
-    StringBuffer returnDate = new StringBuffer();
-    if (date!=null) {
-      if (!date.substring(5,6).equalsIgnoreCase("0")) returnDate.append(date.substring(5,7));
-      else returnDate.append(date.substring(6,7));
-    }
-    return returnDate.toString();
-  }
-
-  /**
-   * converts string from format: yyyy-mm-dd__hh:mm:ss.d
-   * to [d]d
-   */
-  public static String dateToDayOfMonth (String date) {
-    StringBuffer returnDate = new StringBuffer();
-    if (date!=null) {
-      if (!date.substring(8,9).equalsIgnoreCase("0")) returnDate.append(date.substring(8,10));
-      else returnDate.append(date.substring(9,10));
-    }
-    return returnDate.toString();
-  }
-
-  /**
-   * converts string from format: yyyy-mm-dd__hh:mm:ss.d
-   * to hh:mm
-   */
-  public static String dateToTime (String date) {
-    StringBuffer returnDate = new StringBuffer();
-    if (date!=null) {
-      returnDate.append(date.substring(11,16));
-    }
-    return returnDate.toString();
-  }
-
-  /**
-   * Splits the provided CSV text into a list. stolen wholesale from
-   * from Jakarta Turbine StrinUtils.java -mh
-   *
-   * @param text      The CSV list of values to split apart.
-   * @param separator The separator character.
-   * @return          The list of values.
-   */
-  public static String[] split(String text, String separator)
-  {
-    StringTokenizer st = new StringTokenizer(text, separator);
-    String[] values = new String[st.countTokens()];
-    int pos = 0;
-    while (st.hasMoreTokens())
-    {
-      values[pos++] = st.nextToken();
-    }
-    return values;
-  }
-
-  /**
-   * Joins the elements of the provided array into a single string
-   * containing a list of CSV elements. Stolen wholesale from Jakarta
-   * Turbine StringUtils.java. -mh
-   *
-   * @param list      The list of values to join together.
-   * @param separator The separator character.
-   * @return          The CSV text.
-   */
-  public static String join(String[] list, String separator)
-  {
-    StringBuffer csv = new StringBuffer();
-    for (int i = 0; i < list.length; i++)
-    {
-      if (i > 0)
-      {
-      csv.append(separator);
-    }
-    csv.append(list[i]);
-    }
-    return csv.toString();
-  }
-
-  /**
-   * Wandelet String in byte[] um.
-   * @param s
-   * @return byte[] des String
-   */
-
-  public static byte[] stringToBytes(String s) {
-    String crlf = System.getProperty("line.separator");
-    if (!crlf.equals("\n"))
-      s = replace(s, "\n", crlf);
-    // byte[] buf = new byte[s.length()];
-    byte[] buf = s.getBytes();
-    return buf;
-  }
-
-  /**
-   * Ersetzt in String <code>s</code> das <code>pattern</code> durch <code>substitute</code>
-   * @param s
-   * @param pattern
-   * @param substitute
-   * @return String mit den Ersetzungen
-   */
-  public static String replace(String s, String pattern, String substitute) {
-    int i = 0, pLen = pattern.length(), sLen = substitute.length();
-    StringBuffer buf = new StringBuffer(s.length());
-    while (true) {
-      int j = s.indexOf(pattern, i);
-      if (j < 0) {
-        buf.append(s.substring(i));
-        break;
-      } else {
-        buf.append(s.substring(i, j));
-        buf.append(substitute);
-        i = j+pLen;
-      }
-    }
-    return buf.toString();
-  }
-
-  /**
    * Ersetzt in String <code>s</code> das Regexp <code>pattern</code> durch <code>substitute</code>
    * @param s
    * @param pattern
@@ -359,28 +210,6 @@ public final class StringUtil {
     }
   }
 
-
-
-
-  /**
-   * F?gt einen Separator an den Pfad an
-   * @param path
-   * @return Pfad mit Separator am Ende
-   */
-  public static final String addSeparator (String path) {
-    return  path.length() == 0 || path.endsWith(File.separator) ? path : path
-                          + File.separatorChar;
-  }
-
-  /**
-   * F?gt ein <code>/</code> ans ende des Strings and
-   * @param path
-   * @return Pfad mit <code>/</code> am Ende
-   */
-  public static final String addSlash (String path) {
-    return  path.length() == 0 || path.endsWith("/") ? path : path + '/';
-  }
-
   /**
    * L?scht <code>/</code> am Ende des Strings, falls vorhanden
    * @param path
@@ -392,25 +221,6 @@ public final class StringUtil {
   }
 
   /**
-   * Checks to see if the path is absolute by looking for a leading file
-   * separater
-   * @param path
-   * @return
-   */
-  public static boolean isAbsolutePath (String path) {
-    return  path.startsWith(File.separator);
-  }
-
-  /**
-   * L?scht Slash am Anfang des Strings
-   * @param path
-   * @return
-   */
-  public static String removeFirstSlash (String path) {
-    return  path.startsWith("/") ? path.substring(1) : path;
-  }
-
-  /**
    * formatiert eine Zahl (0-99) zweistellig (z.B. 5 -> 05)
    * @return zwistellige Zahl
    */
@@ -428,80 +238,6 @@ public final class StringUtil {
   }
 
   /**
-   * Konvertiert Unix-Linefeeds in Win-Linefeeds
-   * @param s
-   * @return Konvertierter String
-   */
-  public static String unixLineFeedsToWin(String s) {
-    int i = -1;
-    while (true) {
-      i = s.indexOf('\n', i+1);
-      if (i < 0) break;
-      if ((i == 0 || s.charAt(i-1) != '\r') &&
-          (i == s.length()-1 || s.charAt(i+1) != '\r')) {
-        s = s.substring(0, i)+'\r'+s.substring(i);
-        i++;
-      }
-    }
-    return s;
-  }
-
- /**
-  * schnellere Variante der String.toLowerCase()-Routine
-  *
-  * @return String in Kleinbuchsten
-  */
-  public static String toLowerCase(String s) {
-    int l = s.length();
-    char[] a = new char[l];
-    for (int i = 0; i < l; i++)
-      a[i] = Character.toLowerCase(s.charAt(i));
-    return new String(a);
-  }
-
-  /**
-   * Findet <code>element</code> im String-Array <code>array</code>
-   * @param array
-   * @param element
-   * @return Fundstelle als int oder -1
-   */
-  public static int indexOf(String[] array, String element) {
-    if (array != null)
-      for (int i = 0; i < array.length; i++)
-        if (array[i].equals(element))
-          return i;
-    return -1;
-  }
-
-  /**
-   * Testet auf Vorkommen von <code>element</code> in <code>array</code>
-   * @param array String-Array
-   * @param element
-   * @return true wenn <code>element</code> vorkommt, sonst false
-   */
-  public static boolean contains(String[] array, String element) {
-    return indexOf(array, element) >= 0;
-  }
-
-  /**
-   * Ermittelt CRC-Pr?fsumme von String <code>s</code>
-   * @param s
-   * @return CRC-Pr?fsumme
-   */
-  public static int getCRC(String s) {
-    int h = 0;
-    char val[] = s.toCharArray();
-    int len = val.length;
-
-    for (int i = 0 ; i < len; i++) {
-      h &= 0x7fffffff;
-      h = (((h >> 30) | (h << 1)) ^ (val[i]+i));
-    }
-
-    return (h << 8) | (len & 0xff);
-  }
-
-  /**
    * Liefert Default-Wert def zur?ck, wenn String <code>s</code>
    * kein Integer ist.
    *
@@ -518,55 +254,6 @@ public final class StringUtil {
     }
   }
 
-  /**
-   * Liefert Defaultwert def zur?ck, wenn s nicht zu einem float geparsed werden kann.
-   * @param s
-   * @param def
-   * @return geparster float oder def
-   */
-  public static float parseFloat(String s, float def) {
-    if (s == null) return def;
-    try {
-      return new Float(s).floatValue();
-    } catch (NumberFormatException e) {
-      return def;
-    }
-  }
-
-  /**
-   * Findet Ende eines Satzes in String <code>text</code>
-   * @param text
-   * @param startIndex
-   * @return index des Satzendes, oder -1
-   */
-  public static int findEndOfSentence(String text, int startIndex) {
-    while (true) {
-      int i = text.indexOf('.', startIndex);
-      if (i < 0) return -1;
-      if (i > 0 && !Character.isDigit(text.charAt(i-1)) &&
-          (i+1 >= text.length()
-          || text.charAt(i+1) == ' '
-          || text.charAt(i+1) == '\n'
-          || text.charAt(i+1) == '\t'))
-        return i+1;
-      startIndex = i+1;
-    }
-  }
-
-  /**
-   * Findet Wortende in String <code>text</code> ab <code>startIndex</code>
-   * @param text
-   * @param startIndex
-   * @return Index des Wortendes, oder -1
-   */
-  public static int findEndOfWord(String text, int startIndex) {
-    int i = text.indexOf(' ', startIndex),
-    j = text.indexOf('\n', startIndex);
-    if (i < 0) i = text.length();
-    if (j < 0) j = text.length();
-    return Math.min(i, j);
-  }
-
 
   /**
    *  convertNewline2P ist eine regex-routine zum umwandeln von 2 oder mehr newlines (\n)
@@ -713,5 +400,40 @@ public final class StringUtil {
     return content;
   }
 
+  /**
+   * Converts mir's horrible internal date format (yyyy-MM-dd HH:mm:ss+zz) into a java Date
+   *
+   * @param anInternalDate
+   * @return
+   */
+  public static Date convertMirInternalDateToDate(String anInternalDate) {
+    Calendar calendar = new GregorianCalendar();
+
+    int year;
+    int month;
+    int day;
+    int hours;
+    int minutes;
+    int seconds;
+    int timezoneOffset;
+
+    year = Integer.parseInt(anInternalDate.substring(0,4));
+    month = Integer.parseInt(anInternalDate.substring(5,7));
+    day = Integer.parseInt(anInternalDate.substring(8,10));
+    hours = Integer.parseInt(anInternalDate.substring(11,13));
+    minutes = Integer.parseInt(anInternalDate.substring(14,16));
+    seconds = Integer.parseInt(anInternalDate.substring(17,19));
+
+    timezoneOffset = Integer.parseInt(anInternalDate.substring(20,22));
+    if (anInternalDate.charAt(19) == '-')
+      timezoneOffset = -timezoneOffset;
+
+    calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
+    calendar.set(year, month-1, day, hours, minutes, seconds);
+    calendar.add(Calendar.HOUR, -timezoneOffset);
+
+    return calendar.getTime();
+  }
+
 }
 
index 8bf57cb..e4f3da1 100755 (executable)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
  * If you do not wish to do so, delete this exception statement from your version.
  */
 package mir.producer;
@@ -47,10 +47,9 @@ public class NodedProducer implements Producer {
     verb = aVerb;
     baseValues = aBaseValues;
     isAborted = false;
-    isAborted = false;
   }
 
-  public void produce( LoggerWrapper aLogger ) throws ProducerFailure, ProducerExc {
+  public boolean produce( LoggerWrapper aLogger ) throws ProducerFailure, ProducerExc {
     Map valueMap;
 
     valueMap = new HashMap();
@@ -61,6 +60,7 @@ public class NodedProducer implements Producer {
 
     synchronized(this) {
       isFinished=true;
+      return !isAborted;
     }
   };
 
index 776049c..a7ffe93 100755 (executable)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
  * If you do not wish to do so, delete this exception statement from your version.
  */
 package mir.producer;
@@ -32,6 +32,14 @@ package mir.producer;
 import mir.log.LoggerWrapper;
 
 public interface Producer {
-  public void produce( LoggerWrapper aLogger ) throws ProducerFailure, ProducerExc;
+  /**
+   *
+   *
+   * @param aLogger
+   * @return <code>false</code> if aborted,<code>true</code> if not
+   * @throws ProducerFailure
+   * @throws ProducerExc
+   */
+  public boolean produce( LoggerWrapper aLogger ) throws ProducerFailure, ProducerExc;
   public void abort();
 }
index 12df8a9..4a158d9 100755 (executable)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
  * If you do not wish to do so, delete this exception statement from your version.
  */
 package mir.servlet;
@@ -134,7 +134,7 @@ public abstract class ServletModule {
 
   public void redirect(HttpServletResponse aResponse, String aQuery) throws ServletModuleExc, ServletModuleFailure {
     try {
-      aResponse.sendRedirect(MirPropertiesConfiguration.instance().getString("RootUri") + "/Mir?"+aQuery);
+      aResponse.sendRedirect(aResponse.encodeRedirectURL(MirPropertiesConfiguration.instance().getString("RootUri") + "/Mir?"+aQuery));
     }
     catch (Throwable t) {
       throw new ServletModuleFailure("ServletModule.redirect: " +t.getMessage(), t);
index fb7de4f..7a3034e 100755 (executable)
@@ -76,7 +76,7 @@ import mir.util.JDBCStringRoutines;
  * Treiber, Host, User und Passwort, ueber den der Zugriff auf die
  * Datenbank erfolgt.
  *
- * @version $Id: Database.java,v 1.44.2.3 2003/05/26 03:29:46 zapata Exp $
+ * @version $Id: Database.java,v 1.44.2.4 2003/06/23 15:24:06 zapata Exp $
  * @author rk
  *
  */
@@ -117,11 +117,15 @@ public class Database implements StorageObject {
   private String database_url;
   private int defaultLimit;
   protected DatabaseAdaptor theAdaptor;
-  private SimpleDateFormat _dateFormatterOut =
-    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-  private SimpleDateFormat _dateFormatterIn =
-    new SimpleDateFormat("yyyy-MM-dd HH:mm");
-  private Calendar _cal = new GregorianCalendar();
+  TimeZone timezone;
+  SimpleDateFormat internalDateFormat;
+  SimpleDateFormat userInputDateFormat;
+/*
+  private SimpleDateFormat _dateFormatterOut;
+  private SimpleDateFormat _dateFormatterIn;
+  _dateFormatterOut = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+  _dateFormatterIn = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+*/
 
   /**
    * Kontruktor bekommt den Filenamen des Konfigurationsfiles ?bergeben.
@@ -141,6 +145,13 @@ public class Database implements StorageObject {
       throw new StorageObjectFailure(e);
     }
     logger = new LoggerWrapper("Database");
+    timezone = TimeZone.getTimeZone(configuration.getString("Mir.DefaultTimezone"));
+    internalDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    internalDateFormat.setTimeZone(timezone);
+
+    userInputDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+    userInputDateFormat.setTimeZone(timezone);
+
 
     String theAdaptorName = configuration.getString("Database.Adaptor");
     defaultLimit = Integer.parseInt(configuration.getString("Database.Limit"));
@@ -349,14 +360,20 @@ public class Database implements StorageObject {
 
             if (!rs.wasNull()) {
               java.util.Date date = new java.util.Date(timestamp.getTime());
-              outValue = _dateFormatterOut.format(date);
-              _cal.setTime(date);
-
-              int offset =
-                  _cal.get(Calendar.ZONE_OFFSET) + _cal.get(Calendar.DST_OFFSET);
-              String tzOffset =
-                  StringUtil.zeroPaddingNumber(offset / _millisPerHour, 2, 2);
-              outValue = outValue + "+" + tzOffset;
+
+              Calendar calendar = new GregorianCalendar();
+              calendar.setTime(date);
+              calendar.setTimeZone(timezone);
+              outValue = internalDateFormat.format(date);
+
+              int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
+              String tzOffset = StringUtil.zeroPaddingNumber(Math.abs(offset) / _millisPerHour, 2, 2);
+
+              if (offset<0)
+                outValue = outValue + "-";
+              else
+                outValue = outValue + "+";
+              outValue = outValue + tzOffset;
             }
 
             break;
@@ -958,10 +975,11 @@ public class Database implements StorageObject {
 
         // TimeStamp stuff
         try {
-          java.util.Date d = _dateFormatterIn.parse(dateString);
-          Timestamp tStamp = new Timestamp(d.getTime());
-          sql.append(",webdb_create='" + tStamp.toString() + "'");
-        } catch (ParseException e) {
+          java.util.Date d = userInputDateFormat.parse(dateString);
+//          Timestamp tStamp = new Timestamp(d.getTime());
+          sql.append(",webdb_create='" + JDBCStringRoutines.formatDate(d) + "'");
+        }
+        catch (ParseException e) {
           throw new StorageObjectFailure(e);
         }
       }
diff --git a/source/mir/util/DateToMapAdapter.java b/source/mir/util/DateToMapAdapter.java
deleted file mode 100755 (executable)
index 0115984..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 The Mir-coders group
- *
- * This file is part of Mir.
- *
- * Mir is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Mir is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mir; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
- * If you do not wish to do so, delete this exception statement from your version.
- */
-package mir.util;
-
-import java.text.SimpleDateFormat;
-import java.util.AbstractMap;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.HashSet;
-import java.util.Set;
-
-import mir.misc.StringUtil;
-
-public class DateToMapAdapter extends AbstractMap {
-  Date date;
-
-  public DateToMapAdapter(Date aDate) {
-    date = aDate;
-  }
-
-  public Object get(Object aKey) {
-    if (aKey instanceof String) {
-      try {
-        // ML: quick fix to allow for the dc encoding now...
-        if (((String) aKey).equals("dc")) {
-          GregorianCalendar calendar = new GregorianCalendar();
-          calendar.setTime(date);
-          return StringUtil.date2w3DateTime(calendar);
-        }
-        else
-          return new SimpleDateFormat((String) aKey).format(date);
-      }
-      catch (Throwable t) {
-        throw new RuntimeException( "Can't format date with format " + (String) aKey + ": " + t.getMessage());
-      }
-    }
-    else return null;
-  }
-
-  public Set entrySet() {
-    return new HashSet();
-  }
-}
\ No newline at end of file
index d51483a..f6ffd46 100755 (executable)
@@ -1,8 +1,21 @@
 package mir.util;
 
-import java.util.*;
-import java.text.*;
-import mir.generator.*;
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.AbstractMap;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+
+import mir.generator.Generator;
+import mir.generator.GeneratorExc;
+import mir.generator.GeneratorFailure;
+import mir.misc.StringUtil;
 
 public class GeneratorFormatAdapters {
   public static class NumberFormatAdapter {
@@ -13,22 +26,16 @@ public class GeneratorFormatAdapters {
     }
 
     public Generator.GeneratorFunction getFormat() {
-      return new NumberFormattingFunction(value);
+      return new NumberFormattingFunction();
     }
 
-    private static class NumberFormattingFunction implements Generator.GeneratorFunction {
-      private Number value;
-
-      public NumberFormattingFunction(Number aValue) {
-        value = aValue;
-      }
-
+    private class NumberFormattingFunction implements Generator.GeneratorFunction {
       public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure {
         try {
-          if (aParameters.size()!=1 || !(aParameters.get(0) instanceof String) )
+          if (aParameters.size() != 1 || ! (aParameters.get(0)instanceof String))
             throw new GeneratorExc("NumberFormattingFunction <format> : exactly 1 string parameter expected");
 
-          return new DecimalFormat((String) (aParameters.get(0))).format(value);
+          return new DecimalFormat( (String) (aParameters.get(0))).format(value);
         }
         catch (GeneratorExc e) {
           throw e;
@@ -40,4 +47,121 @@ public class GeneratorFormatAdapters {
     }
   }
 
+  public static class DateFormatAdapter {
+    private Date value;
+    private TimeZone defaultTimezone;
+    private String defaultTimezoneName;
+
+    public DateFormatAdapter(Date aValue, String aDefaultTimezone) {
+      value = aValue;
+      defaultTimezoneName = aDefaultTimezone;
+      defaultTimezone = null;
+    }
+
+    private TimeZone getDefaultTimezone() {
+      if (defaultTimezone == null) {
+        try {
+          defaultTimezone = TimeZone.getTimeZone(defaultTimezoneName);
+        }
+        catch (Throwable t) {
+        }
+
+        if (defaultTimezone==null)
+          defaultTimezone = TimeZone.getDefault();
+      }
+
+      return defaultTimezone;
+    }
+
+    public Generator.GeneratorFunction getFormat() {
+      return new DateFormattingFunction();
+    }
+
+    public Map getFormatted() {
+      return new DateToMapAdapter();
+    }
+
+    public Date getDate() {
+      return value;
+    }
+
+    private class DateFormattingFunction implements Generator.GeneratorFunction {
+      public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure {
+        try {
+          if (aParameters.size() < 1 || aParameters.size() > 2 ||
+              !(aParameters.get(0) instanceof String) || (aParameters.size()>1 && ! (aParameters.get(1) instanceof String)))
+            throw new GeneratorExc("DateFormattingFunction <format> [timezone]: 1 or 2 string parameters expected");
+
+          SimpleDateFormat dateFormat = new SimpleDateFormat( (String) (aParameters.get(0)));
+
+          TimeZone timezone = null;
+          if (aParameters.size() > 1) {
+            try  {
+              timezone = TimeZone.getTimeZone( (String) aParameters.get(1));
+            }
+            catch (Throwable t) {
+
+            }
+          }
+
+          if (timezone == null)
+            timezone = getDefaultTimezone();
+
+          dateFormat.setTimeZone(timezone);
+
+          return dateFormat.format(value);
+        }
+        catch (GeneratorExc e) {
+          throw e;
+        }
+        catch (Throwable t) {
+          throw new GeneratorFailure("DateFormattingFunction: " + t.getMessage(), t);
+        }
+      };
+    }
+
+    /**
+     *
+     * retained for backwards compatibility
+     *
+     * <p>Title: </p>
+     * <p>Description: </p>
+     * <p>Copyright: Copyright (c) 2003</p>
+     * <p>Company: </p>
+     * @author not attributable
+     * @version 1.0
+     */
+
+    public class DateToMapAdapter extends AbstractMap {
+      public Object get(Object aKey) {
+        if (aKey instanceof String) {
+          try {
+            // ML: quick fix to allow for the dc encoding now...
+            if ( ( (String) aKey).equals("dc")) {
+              GregorianCalendar calendar = new GregorianCalendar();
+              calendar.setTime(value);
+              calendar.setTimeZone(defaultTimezone);
+              return StringUtil.date2w3DateTime(calendar);
+            }
+            else {
+              DateFormat dateFormat = new SimpleDateFormat( (String) aKey);
+              dateFormat.setTimeZone(defaultTimezone);
+
+              return dateFormat.format(value);
+            }
+          }
+          catch (Throwable t) {
+            throw new RuntimeException("Can't format date with format " + (String) aKey + ": " + t.getMessage());
+          }
+        }
+        else
+          return null;
+      }
+
+      public Set entrySet() {
+        return new HashSet();
+      }
+    }
+
+  }
 }
\ No newline at end of file
index 951e458..54dbea5 100755 (executable)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
  * If you do not wish to do so, delete this exception statement from your version.
  */
 
 package mir.util;
 
+import java.util.*;
+
 import javax.servlet.http.HttpServletRequest;
 
 public class HTTPRequestParser {
@@ -74,6 +76,24 @@ public class HTTPRequestParser {
     }
   }
 
+  public List getParameterList(String aName) {
+    try {
+      List result = new Vector();
+      String items[] = request.getParameterValues(aName);
+
+      if (items!=null) {
+        for (int i=0; i<items.length; i++) {
+          result.add(items[i]);
+        }
+      }
+
+      return result;
+    }
+    catch (Throwable t) {
+      throw new RuntimeException("HTTPRequestParser.getParameterList: " + t.getMessage());
+    }
+  }
+
   public int getIntegerWithDefault(String aName, int aDefault) {
     int result = aDefault;
     String value = getParameter(aName);
index 136c94a..cae60e5 100755 (executable)
@@ -53,6 +53,8 @@ public class JDBCStringRoutines {
   }
 
   public static String formatDate(Date aDate) {
-    return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(aDate);
+    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm 'UTC'");
+    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+    return dateFormat.format(aDate);
   }
 }
\ No newline at end of file
index adf4034..5cb276b 100755 (executable)
@@ -30,8 +30,6 @@
 
 package mircoders.global;
 
-import gnu.regexp.RE;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -43,24 +41,26 @@ import java.util.List;
 import java.util.Map;
 import java.util.Random;
 import java.util.Vector;
-
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.collections.ExtendedProperties;
+import gnu.regexp.RE;
+
+import mir.config.MirPropertiesConfiguration;
 import mir.entity.Entity;
 import mir.log.LoggerWrapper;
 import mir.session.HTTPAdapters;
 import mir.session.Request;
-import mir.util.DateToMapAdapter;
+import mir.util.GeneratorFormatAdapters;
 import mir.util.InternetFunctions;
 import mir.util.StringRoutines;
-import mircoders.entity.*;
+import mircoders.entity.EntityComment;
 import mircoders.entity.EntityContent;
+import mircoders.entity.EntityUsers;
 import mircoders.localizer.MirAdminInterfaceLocalizer;
 
-import org.apache.commons.collections.ExtendedProperties;
-
 
 public class Abuse {
   private List filters;
@@ -311,26 +311,31 @@ public class Abuse {
 
   public List getLog() {
     synchronized(log) {
-      List result = new Vector();
+      try {
+        List result = new Vector();
+
+        Iterator i = log.iterator();
+        while (i.hasNext()) {
+          LogEntry logEntry = (LogEntry) i.next();
+          Map entry = new HashMap();
+
+          entry.put("ip", logEntry.getIpNumber());
+          entry.put("id", logEntry.getId());
+          entry.put("timestamp", new GeneratorFormatAdapters.DateFormatAdapter(logEntry.getTimeStamp(), MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone")));
+          if (logEntry.getIsArticle())
+            entry.put("type", "content");
+          else
+            entry.put("type", "comment");
+          entry.put("browser", logEntry.getBrowserString());
+
+          result.add(entry);
+        }
 
-      Iterator i = log.iterator();
-      while (i.hasNext()) {
-        LogEntry logEntry = (LogEntry) i.next();
-        Map entry = new HashMap();
-
-        entry.put("ip", logEntry.getIpNumber());
-        entry.put("id", logEntry.getId());
-        entry.put("timestamp", new DateToMapAdapter(logEntry.getTimeStamp()));
-        if (logEntry.getIsArticle())
-          entry.put("type", "content");
-        else
-          entry.put("type", "comment");
-        entry.put("browser", logEntry.getBrowserString());
-
-        result.add(entry);
+        return result;
+      }
+      catch (Throwable t) {
+        throw new RuntimeException(t.toString());
       }
-
-      return result;
     }
   }
 
index 22a6be7..4fafe7f 100755 (executable)
@@ -37,17 +37,22 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Vector;
+import java.util.*;
+
+import mir.log.*;
 
 // important: objects passed as data must not be altered once put into a job
 
 public class JobQueue {
-  private Vector jobs;
-  private Vector finishedJobs;
-  private Map dataToJob;
-  private Map identifierToJob;
+  private Vector jobHandlers;
+  private Map identifierToJobHandler;
   private int nrJobs;
+  private int jobCleanupTreshold;
+  private JobQueueRunner queueRunner;
+  private Thread thread;
+  private LoggerWrapper logger;
 
+  public static final int STATUS_CREATED = -1;
   public static final int STATUS_PENDING = 0;
   public static final int STATUS_PROCESSING = 1;
   public static final int STATUS_PROCESSED = 2;
@@ -60,143 +65,191 @@ public class JobQueue {
 
   public static final int FINISHEDJOBS_LOGSIZE = 10;
 
-  public JobQueue() {
-    finishedJobs = new Vector();
-    jobs = new Vector();
-    dataToJob = new HashMap();
-    identifierToJob = new HashMap();
+  public JobQueue(LoggerWrapper aLogger) {
+    logger = aLogger;
+    jobHandlers = new Vector();
+    identifierToJobHandler = new HashMap();
     nrJobs = 0;
+    jobCleanupTreshold = 1000;
+    queueRunner = new JobQueueRunner(logger);
+    thread = new Thread(queueRunner);
+    thread.start();
   }
 
-  public String appendJob(Object aData) {
-    synchronized (jobs) {
-      Job job = new Job(aData, Integer.toString(nrJobs));
+  public String appendJob(Job aJob, String aDescription) {
+    synchronized (jobHandlers) {
+      JobHandler jobHandler = new JobHandler(aJob, Integer.toString(nrJobs), aDescription);
       nrJobs++;
-      jobs.add(job);
-      dataToJob.put(aData, job);
-      identifierToJob.put(job.getIdentifier(), job);
-      return job.getIdentifier();
+      jobHandlers.add(jobHandler);
+      identifierToJobHandler.put(jobHandler.getIdentifier(), jobHandler);
+      jobHandler.setPending();
+
+      return jobHandler.getIdentifier();
     }
   }
 
-  public Object acquirePendingJob() {
-    synchronized (jobs) {
-      int priorityFound= 0;
-      Job jobFound;
+  public List getJobsInfo() {
+    List result = new Vector();
 
-      do {
-        jobFound = null;
-        Iterator i = jobs.iterator();
-        while (i.hasNext()) {
-          Job job = (Job) i.next();
+    synchronized (jobHandlers) {
+      Iterator i = jobHandlers.iterator();
 
-          if (job.isPending() && (jobFound==null || priorityFound<job.getPriority())) {
-            jobFound = job;
-            priorityFound = job.getPriority();
-          }
-        }
+      while (i.hasNext()) {
+        result.add(((JobHandler) i.next()).getJobInfo());
       }
-      while (jobFound!=null && !jobFound.setProcessing());
-
-      if (jobFound!=null)
-        return jobFound.getData();
-      else
-        return null;
     }
-  }
 
-  private void finishJob(Job aJob) {
-    synchronized (jobs) {
-      identifierToJob.remove(aJob.identifier);
-      jobs.remove(aJob);
-      finishedJobs.insertElementAt(aJob, 0);
-      if (finishedJobs.size()>FINISHEDJOBS_LOGSIZE)
-        finishedJobs.remove(finishedJobs.size()-1);
-    }
+    return result;
   }
 
-  public void jobProcessed(Object aData) {
-    synchronized (jobs) {
-      Job job = (Job) dataToJob.get(aData);
+  private void cleanupJobList() {
+    synchronized (jobHandlers) {
+      Iterator i = jobHandlers.iterator();
+
+      Calendar tresholdCalendar = new GregorianCalendar();
+      tresholdCalendar.add(Calendar.SECOND, -jobCleanupTreshold);
+      Date treshold = tresholdCalendar.getTime();
 
-      if (job!=null) {
-        job.setProcessed();
-        finishJob(job);
+      while (i.hasNext()) {
+        JobHandler jobHandler = (JobHandler) i.next();
+
+        synchronized (jobHandler) {
+          if (jobHandler.isFinished() && jobHandler.getLastChange().before(treshold)) {
+            jobHandlers.remove(jobHandler);
+          }
+        }
       }
     }
   }
 
-  public void jobAborted(Object aData) {
-    synchronized (jobs) {
-      Job job = (Job) dataToJob.get(aData);
+  private JobHandler acquirePendingJob() {
+    synchronized (jobHandlers) {
+      int priorityFound= 0;
+      JobHandler jobFound;
+
+      jobFound = null;
+      Iterator i = jobHandlers.iterator();
+      while (i.hasNext()) {
+        JobHandler job = (JobHandler) i.next();
 
-      if (job!=null) {
-        job.setAborted();
-        finishJob(job);
+        if (job.isPending() && (jobFound==null || priorityFound<job.getPriority())) {
+          jobFound = job;
+          priorityFound = job.getPriority();
+        }
       }
+
+      return jobFound;
     }
   }
 
-  public void cancelJob(Object aData) {
-    synchronized (jobs) {
-      Job job = (Job) dataToJob.get(aData);
+  public void cancelJobs(List aJobs) {
+    synchronized (jobHandlers) {
+      Iterator i = aJobs.iterator();
 
-      if (job!=null && job.setCancelled()) {
-        finishJob(job);
+      while (i.hasNext()) {
+        ((JobHandler) identifierToJobHandler.get(i.next())).cancelOrAbortJob();
       }
     }
   }
 
-  public void makeJobListSnapshots(List aJobList, List aFinishedJobList) {
-    synchronized (jobs) {
-      aJobList.addAll(makeJobListSnapshot());
-      aFinishedJobList.addAll(makeFinishedJobListSnapshot());
-    }
+  public interface Job {
+    void abort();
+
+    /**
+     *
+     *
+     * @return <code>true</code> if terminated normally, <code>false</code> if aborted
+     */
+    boolean run();
   }
 
-  public List makeJobListSnapshot() {
-    synchronized (jobs) {
-      return (List) jobs.clone();
+  public static class JobInfo {
+    private String identifier;
+    private Date lastChange;
+    private int status;
+    private long runningTime;
+    private int priority;
+    private String description;
+
+    private JobInfo(String aDescription, int aStatus, Date aLastChange, String anIdentifier, long aRunningTime, int aPriority) {
+      description = aDescription;
+      lastChange = aLastChange;
+      status = aStatus;
+      identifier = anIdentifier;
+      priority = aPriority;
+      runningTime = aRunningTime;
     }
-  }
 
-  public List makeFinishedJobListSnapshot() {
-    synchronized (jobs) {
-      return (List) finishedJobs.clone();
+    public String getDescription() {
+      return description;
+    }
+
+    public int getStatus() {
+      return status;
+    }
+
+    public int getPriority() {
+      return priority;
+    }
+
+    public Date getLastChange() {
+      return lastChange;
+    }
+
+    public String getIdentifier() {
+      return identifier;
+    }
+
+    public long getRunningTime() {
+      return runningTime;
     }
   }
 
-  public class Job implements Cloneable {
-    private Object data;
+  public class JobHandler {
+    private Job job;
+    private String identifier;
+    private String description;
+
     private Date lastChange;
     private long starttime;
     private long endtime;
-    private String identifier;
     private int status;
     private int priority;
     private boolean hasRun;
 
-    public Job(Object aData, String anIdentifier, int aStatus, int aPriority, Date aLastChange) {
-      data = aData;
-      status = aStatus;
+    public JobHandler(Job aJob, String anIdentifier, String aDescription, int aPriority) {
+      job = aJob;
+      description = aDescription;
       identifier = anIdentifier;
       priority = aPriority;
-      lastChange = aLastChange;
-
-      hasRun = false;
+      status = STATUS_CREATED;
     }
 
-    public Job(Object aData, String anIdentifier, int aStatus, int aPriority) {
-      this(aData, anIdentifier, aStatus, aPriority, (new GregorianCalendar()).getTime());
+    public JobHandler(Job aJob, String anIdentifier, String aDescription) {
+      this(aJob, anIdentifier, aDescription, PRIORITY_NORMAL);
     }
 
-    public Job(Object aData, String anIdentifier) {
-      this(aData, anIdentifier, STATUS_PENDING, PRIORITY_NORMAL);
+    public JobInfo getJobInfo() {
+      return new JobInfo(getDescription(), getStatus(), getLastChange(), getIdentifier(), getRunningTime(), priority);
     }
 
-    public Object getData() {
-      return data;
-    }
+    private void runJob() {
+      if (setProcessing()) {
+        if (job.run())
+          setProcessed();
+        else
+          setAborted();
+      }
+    };
+
+    private void cancelOrAbortJob() {
+      synchronized (this) {
+        if (isPending())
+          setCancelled();
+        if (isProcessing())
+          job.abort();
+      }
+    };
 
     public int getStatus() {
       synchronized(this) {
@@ -204,46 +257,52 @@ public class JobQueue {
       }
     }
 
-    public Date getLastChange() {
-      return lastChange;
-    }
-
     public String getIdentifier() {
       return identifier;
     }
 
+    public String getDescription() {
+      return description;
+    }
+
     public long getRunningTime() {
-      long result = 0;
+      synchronized(this) {
+        long result = 0;
 
-      if (hasRun) {
-        if (isFinished())
-          result = endtime;
-        else
-          result = System.currentTimeMillis();
+        if (hasRun) {
+          if (isFinished())
+            result = endtime;
+          else
+            result = System.currentTimeMillis();
 
-        result = result-starttime;
-      }
+          result = result - starttime;
+        }
 
-      return result;
+        return result;
+      }
     }
 
     public int getPriority() {
       return priority;
     }
 
-    protected boolean setProcessing() {
+    private boolean setProcessing() {
       return setStatus(STATUS_PENDING, STATUS_PROCESSING);
     }
 
-    protected void setProcessed() {
+    private void setProcessed() {
       setStatus(STATUS_PROCESSING, STATUS_PROCESSED);
     }
 
-    protected void setAborted() {
+    private void setAborted() {
       setStatus(STATUS_PROCESSING, STATUS_ABORTED);
     }
 
-    protected boolean setCancelled() {
+    private void setPending() {
+      setStatus(STATUS_CREATED, STATUS_PENDING);
+    }
+
+    private boolean setCancelled() {
       return setStatus(STATUS_PENDING, STATUS_CANCELLED);
     }
 
@@ -271,6 +330,12 @@ public class JobQueue {
       return getStatus() == STATUS_PENDING;
     }
 
+    public Date getLastChange() {
+      synchronized (this) {
+        return lastChange;
+      }
+    }
+
     private boolean setStatus(int anOldStatus, int aNewStatus) {
       synchronized(this) {
         if (status == anOldStatus) {
@@ -291,10 +356,37 @@ public class JobQueue {
         }
       }
     }
+  }
 
-    protected Object clone() {
-      synchronized(this) {
-        return new Job(data, identifier, status, priority, lastChange);
+  private class JobQueueRunner implements Runnable {
+    private LoggerWrapper logger;
+
+    public JobQueueRunner(LoggerWrapper aLogger) {
+      logger = aLogger;
+    }
+
+    public void run() {
+      logger.debug("starting JobQueueRunner");
+
+      try {
+        while (true) {
+          JobHandler job = acquirePendingJob();
+          if (job != null) {
+            logger.debug("  starting job ("+job.getIdentifier()+"): " +job.getDescription());
+            job.runJob();
+            logger.debug("  finished job ("+job.getIdentifier()+"): " +job.getDescription());
+          }
+          else {
+            try {
+              Thread.sleep(1500);
+            }
+            catch (InterruptedException e) {
+            }
+          }
+        }
+      }
+      finally {
+        logger.warn("JobQueueRunner terminated");
       }
     }
   }
index b957ec2..6c6f282 100755 (executable)
@@ -40,7 +40,8 @@ import mir.log.LoggerToWriterAdapter;
 import mir.log.LoggerWrapper;
 import mir.producer.Producer;
 import mir.producer.ProducerFactory;
-import mir.util.DateToMapAdapter;
+import mir.util.*;
+import mir.config.*;
 import mir.util.StringRoutines;
 import multex.Exc;
 import multex.Failure;
@@ -48,22 +49,22 @@ import multex.Failure;
 public class ProducerEngine {
 //  private Map producers;
   private JobQueue producerJobQueue;
-  private Thread queueThread;
   private LoggerWrapper logger;
 
 
   protected ProducerEngine() {
-    producerJobQueue = new JobQueue();
     logger = new LoggerWrapper("Producer");
-
-    queueThread = new Thread(new ProducerJobQueueThread());
-    queueThread.start();
+    producerJobQueue = new JobQueue(new LoggerWrapper("Producer.Queue"));
   }
 
   public void addJob(String aProducerFactory, String aVerb) {
-    producerJobQueue.appendJob(new ProducerJob(aProducerFactory, aVerb));
+    producerJobQueue.appendJob(new ProducerJob(aProducerFactory, aVerb), aProducerFactory+"."+aVerb);
   }
 
+  public void cancelJobs(List aJobs) {
+    producerJobQueue.cancelJobs(aJobs);
+  };
+
   public void addTask(ProducerTask aTask) {
     addJob(aTask.getProducer(), aTask.getVerb());
   }
@@ -76,57 +77,61 @@ public class ProducerEngine {
     }
   }
 
-  private String convertStatus(JobQueue.Job aJob) {
-    if (aJob.hasBeenProcessed())
-      return "processed";
-    if (aJob.isProcessing())
-      return "processing";
-    if (aJob.isPending())
-      return "pending";
-    if (aJob.isCancelled())
-      return "cancelled";
-    if (aJob.hasBeenAborted())
-      return "aborted";
-
+  private String convertStatus(JobQueue.JobInfo aJob) {
+    switch (aJob.getStatus()) {
+      case JobQueue.STATUS_ABORTED:
+        return "aborted";
+      case JobQueue.STATUS_CANCELLED:
+        return "cancelled";
+      case JobQueue.STATUS_CREATED:
+        return "created";
+      case JobQueue.STATUS_PENDING:
+        return "pending";
+      case JobQueue.STATUS_PROCESSED:
+        return "processed";
+      case JobQueue.STATUS_PROCESSING:
+        return "processing";
+    }
     return "unknown";
   }
 
-  private Map convertJob(JobQueue.Job aJob) {
-    Map result = new HashMap();
-    ProducerJob producerJob = (ProducerJob) aJob.getData();
-
-    result.put("identifier", aJob.getIdentifier());
-    result.put("factory", producerJob.getFactoryName());
-    result.put("verb", producerJob.getVerb());
-    result.put("priority", new Integer(aJob.getPriority()));
-    result.put("runningtime", new Double((double) aJob.getRunningTime()/1000));
-    result.put("status", convertStatus(aJob));
-    result.put("lastchange", new DateToMapAdapter(aJob.getLastChange()));
-
-    return result;
-  }
+  private Map convertJob(JobQueue.JobInfo aJob) {
+    try {
+      Map result = new HashMap();
+      result.put("identifier", aJob.getIdentifier());
+      result.put("description", aJob.getDescription());
+      result.put("priority", new Integer(aJob.getPriority()));
+      result.put("runningtime", new Double( (double) aJob.getRunningTime() / 1000));
+      result.put("status", convertStatus(aJob));
+      result.put("lastchange", new GeneratorFormatAdapters.DateFormatAdapter(aJob.getLastChange(), MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone")));
+      result.put("finished", new Boolean(
+          aJob.getStatus() == JobQueue.STATUS_PROCESSED ||
+          aJob.getStatus() == JobQueue.STATUS_CANCELLED ||
+          aJob.getStatus() == JobQueue.STATUS_ABORTED));
 
-  private void convertJobList(List aSourceJobList, List aDestination) {
-    Iterator i = aSourceJobList.iterator();
-
-    while (i.hasNext())
-      aDestination.add(convertJob((JobQueue.Job) i.next()));
+      return result;
+    }
+    catch (Throwable t) {
+      throw new RuntimeException(t.toString());
+    }
   }
 
-  public List getQueueStatus() {
+  private List convertJobInfoList(List aJobInfoList) {
     List result = new Vector();
-    List pendingJobs = new Vector();
-    List finishedJobs = new Vector();
 
-    producerJobQueue.makeJobListSnapshots(pendingJobs, finishedJobs);
+    Iterator i = aJobInfoList.iterator();
 
-    convertJobList(pendingJobs, result);
-    convertJobList(finishedJobs, result);
+    while (i.hasNext())
+      result.add(convertJob((JobQueue.JobInfo) i.next()));
 
     return result;
   }
 
-private class ProducerJob {
+  public List getQueueStatus() {
+    return convertJobInfoList(producerJobQueue.getJobsInfo());
+  }
+
+  private class ProducerJob implements JobQueue.Job {
     private String factoryName;
     private String verb;
     private Producer producer;
@@ -151,10 +156,11 @@ private class ProducerJob {
       }
     }
 
-    public void execute() {
+    public boolean run() {
       ProducerFactory factory;
       long startTime;
       long endTime;
+      boolean result = false;
       Map startingMap = new HashMap();
 
       startTime = System.currentTimeMillis();
@@ -170,7 +176,7 @@ private class ProducerJob {
             producer = factory.makeProducer(verb, startingMap);
           }
           if (producer!=null) {
-            producer.produce(logger);
+            result = producer.produce(logger);
           }
         }
       }
@@ -180,6 +186,8 @@ private class ProducerJob {
       }
       endTime = System.currentTimeMillis();
       logger.info("Done producing job: " + factoryName + "." + verb + ", time elapsed:" + (endTime-startTime) + " ms");
+
+      return result;
     }
 
     boolean isAborted() {
@@ -187,31 +195,6 @@ private class ProducerJob {
     }
   }
 
-  private class ProducerJobQueueThread implements Runnable {
-    public void run() {
-      logger.debug("starting ProducerJobQueueThread");
-
-      while (true) {
-        ProducerJob job = (ProducerJob) producerJobQueue.acquirePendingJob();
-        if (job!=null) {
-          job.execute();
-          if (job.isAborted())
-            producerJobQueue.jobAborted(job);
-          else
-            producerJobQueue.jobProcessed(job);
-        }
-        else
-        {
-          try {
-            Thread.sleep(1500);
-          }
-          catch (InterruptedException e) {
-          }
-        }
-      }
-    }
-  }
-
   public static class ProducerEngineExc extends Exc {
     public ProducerEngineExc(String aMessage) {
       super(aMessage);
index d56ce9f..97ef36a 100755 (executable)
@@ -89,9 +89,9 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer {
 
   protected void constructContentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure, MirLocalizerExc {
     try {
-      anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create");
-      anEntityAdapterDefinition.addDBDateField("changedate", "webdb_lastchange");
-      anEntityAdapterDefinition.addMirDateField("date", "date");
+      anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
+      anEntityAdapterDefinition.addDBDateField("changedate", "webdb_lastchange", configuration.getString("Mir.DefaultTimezone"));
+      anEntityAdapterDefinition.addMirDateField("date", "date", configuration.getString("Mir.DefaultTimezone"));
       anEntityAdapterDefinition.addCalculatedField("to_topics", new ContentToTopicsField());
       anEntityAdapterDefinition.addCalculatedField("to_comments", new ContentToCommentsField());
       anEntityAdapterDefinition.addCalculatedField("language", new ContentToLanguageField());
@@ -131,7 +131,7 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer {
 
   protected void constructCommentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure {
     try {
-      anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create");
+      anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
       anEntityAdapterDefinition.addCalculatedField("to_content", new CommentToContentField());
       anEntityAdapterDefinition.addCalculatedField("status", new CommentToStatusField());
 
@@ -175,7 +175,7 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer {
       result.addMapping( "commentStatus", DatabaseCommentStatus.getInstance(), new EntityAdapterDefinition());
 
       definition = new EntityAdapterDefinition();
-      definition.addDBDateField("creationdate", "webdb_create");
+      definition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone"));
       result.addMapping( "breakingNews", DatabaseBreaking.getInstance(), definition);
 
       result.addMapping( "imageType", DatabaseImageType.getInstance(), new EntityAdapterDefinition());
index 00d5131..b3ca557 100755 (executable)
@@ -39,9 +39,8 @@ import mir.entity.adapter.EntityAdapter;
 import mir.entity.adapter.EntityIteratorAdapter;
 import mir.log.LoggerWrapper;
 import mir.misc.StringUtil;
-import mir.util.DateToMapAdapter;
-import mir.util.GeneratorExpressionFunctions;
 import mir.util.*;
+import mir.util.GeneratorExpressionFunctions;
 import mir.util.GeneratorIntegerFunctions;
 import mir.util.GeneratorListFunctions;
 import mir.util.GeneratorStringFunctions;
@@ -67,7 +66,7 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL
       configMap.put("openAction", MirGlobal.config().getString("Producer.OpenAction"));
       configMap.put("docRoot", MirGlobal.config().getString("RootUri"));
       configMap.put("actionRoot", MirGlobal.config().getString("RootUri") + "/servlet/Mir");
-      configMap.put("now", new DateToMapAdapter( (new GregorianCalendar()).getTime()));
+      configMap.put("now", new GeneratorFormatAdapters.DateFormatAdapter(new GregorianCalendar().getTime(), MirGlobal.config().getString("Mir.DefaultTimezone")));
       configMap.put("videoHost", MirGlobal.config().getString("Producer.Video.Host"));
       configMap.put("audioHost", MirGlobal.config().getString("Producer.Audio.Host"));
       configMap.put("imageHost", MirGlobal.config().getString("Producer.Image.Host"));
index 389ae61..c0937ca 100755 (executable)
@@ -141,7 +141,7 @@ public class ServletHelper {
 
   public static void redirect(HttpServletResponse aResponse, String aQuery) throws ServletModuleExc, ServletModuleFailure {
     try {
-      aResponse.sendRedirect(MirPropertiesConfiguration.instance().getString("RootUri") + "/Mir?"+aQuery);
+      aResponse.sendRedirect(aResponse.encodeRedirectURL(MirPropertiesConfiguration.instance().getString("RootUri") + "/Mir?"+aQuery));
     }
     catch (Throwable t) {
       throw new ServletModuleFailure("ServletModule.redirect: " +t.getMessage(), t);
index fab7cbd..26af533 100755 (executable)
@@ -36,20 +36,20 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Vector;
-
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.struts.util.MessageResources;
+
 import mir.generator.Generator;
 import mir.log.LoggerWrapper;
 import mir.producer.ProducerFactory;
 import mir.servlet.ServletModule;
 import mir.servlet.ServletModuleFailure;
+import mir.util.HTTPRequestParser;
 import mir.util.ResourceBundleGeneratorFunction;
 import mircoders.global.MirGlobal;
 
-import org.apache.struts.util.MessageResources;
-
 public class ServletModuleProducer extends ServletModule
 {
   private static ServletModuleProducer instance = new ServletModuleProducer();
@@ -79,14 +79,15 @@ public class ServletModuleProducer extends ServletModule
     defaultAction="showProducerQueueStatus";
   }
 
-  public void showMessage(PrintWriter aWriter, Locale aLocale, String aMessage, String anArgument1, String anArgument2) {
+  public void showMessage(HttpServletRequest aRequest, HttpServletResponse aResponse, String aMessage, String anArgument1, String anArgument2) {
     Map responseData;
     try {
-      responseData = new HashMap();
+      responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
       responseData.put("message", aMessage);
       responseData.put("argument1", anArgument1);
       responseData.put("argument2", anArgument2);
-      generateResponse("infomessage.template", aWriter, responseData, aLocale);
+
+      ServletHelper.generateResponse(aResponse.getWriter(), responseData, "infomessage.template");
     }
     catch (Throwable t) {
       throw new ServletModuleFailure(t);
@@ -139,7 +140,7 @@ public class ServletModuleProducer extends ServletModule
     }
   }
 
-  public void produce(HttpServletRequest req, HttpServletResponse res) {
+  public void produce(HttpServletRequest aRequest, HttpServletResponse aResponse) {
     /*
      * This method will only be called by external scripts (e.g. from cron jobs).
      * The output therefore is very simple.
@@ -147,11 +148,11 @@ public class ServletModuleProducer extends ServletModule
      */
 
     try {
-      PrintWriter out = res.getWriter();
+      PrintWriter out = aResponse.getWriter();
 
-      if (req.getParameter("producer")!=null) {
-        String producerParam = req.getParameter("producer");
-        String verbParam = req.getParameter("verb");
+      if (aRequest.getParameter("producer")!=null) {
+        String producerParam = aRequest.getParameter("producer");
+        String verbParam = aRequest.getParameter("verb");
 
         MirGlobal.producerEngine().addJob(producerParam, verbParam);
         out.println("job added");
@@ -165,7 +166,7 @@ public class ServletModuleProducer extends ServletModule
   public void produceAllNew(HttpServletRequest aRequest, HttpServletResponse aResponse) {
     try {
       MirGlobal.localizer().producers().produceAllNew();
-      showMessage(aResponse.getWriter(), getLocale(aRequest), "produceAllNewAddedToQueue", "", "");
+      showMessage(aRequest, aResponse, "produceAllNewAddedToQueue", "", "");
     }
     catch (Throwable t) {
       throw new ServletModuleFailure(t);
@@ -188,7 +189,16 @@ public class ServletModuleProducer extends ServletModule
     }
   }
 
-  public void cancelAbortJob(HttpServletRequest aRequest, HttpServletResponse aResponse)  {
-    // ML: to be coded
+  public void cancel(HttpServletRequest aRequest, HttpServletResponse aResponse)  {
+    try {
+      HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
+      List jobs = new Vector(requestParser.getParameterList("jobid"));
+
+      MirGlobal.producerEngine().cancelJobs(jobs);
+      ServletHelper.redirect(aResponse, "Producer", "showProducerQueueStatus");
+    }
+    catch (Throwable t) {
+      throw new ServletModuleFailure(t);
+    }
   }
 }
index b6b201c..f80a939 100755 (executable)
@@ -23,7 +23,7 @@
       <assign grey="0">      
       <list log as l>
         <if grey=="1"><assign grey="0"><tr class="listrow1"><else><tr class="listrow2"><assign grey="1"> </if>
-          <td>${l.timestamp["yyyy-MM-dd  HH:mm"]}</td>
+          <td>${l.timestamp.format("yyyy-MM-dd  HH:mm")}</td>
           <td>${l.ip}</td>
           <td>
             <if l.type=="content">
index fb51eac..506440b 100755 (executable)
@@ -53,7 +53,7 @@
       ${lang("content.lastchange_date")}:
     </td>
     <td class="listrow2">
-      ${utility.encodeHTML(article.webdb_lastchange)}<br>
+      ${utility.encodeHTML(article.changedate.format("yyyy-MM-dd HH:mm"))}<br>
     </td>
   </tr>
 
@@ -62,7 +62,7 @@
       ${lang("content.create_date")}:
     </td>
     <td class="listrow2">
-      ${utility.encodeHTML(article.webdb_create)}<br>${lang("edit")}:
+      ${utility.encodeHTML(article.creationdate.format("yyyy-MM-dd HH:mm"))}<br>${lang("edit")}:
       <input type="text" size="10" maxlength="16" name="webdb_create" value=""> &nbsp; <span class="small">(yyyy-mm-dd [HH:mm])</span>
     </td>
   </tr>
index 5cbedd8..aa24a48 100755 (executable)
 
 <td valign="top" align="right">
 
-<p class="box" align="left"><b>${lang("producer.jobqueue.title")}</b></p>
+<p class="box" align="left"><b>${lang("producer.jobqueue.title")}</b> <a class="link-box"  href="${config.actionRoot}?${thisurl}">${lang("producer.jobqueue.refresh")}</a></p>
 
+<form method="post" action="${config.actionRoot}">
+      <input type="hidden" name="module" value="Producer">
+      <input type="hidden" name="do" value="cancel">
+      
 <table border="0" cellspacing="3" cellpadding="2">
   <tr >
-    <td class="bg-neutral" colspan="2"><b>${lang("producer.job.name")}</b></td>
-    <td class="bg-neutral" ><b>${lang("producer.job.status")}</b></td>
-    <td class="bg-neutral small" ><b>${lang("producer.job.date")}</b></td>
-    <td class="bg-neutral small" ><b>${lang("producer.job.runningtime")}</b></td>
-    <comment>    
-    <td class="box-head" >&nbsp;</td>
-    </comment>    
+    <td class="bg-neutral"><b>${lang("producer.job.name")}</b></td>
+    <td class="bg-neutral"><b>${lang("producer.job.status")}</b></td>
+    <td class="bg-neutral small"><b>${lang("producer.job.date")}</b></td>
+    <td class="bg-neutral small"><b>${lang("producer.job.runningtime")}</b></td>
+    <td class="bg-neutral">&nbsp;</td>
   </tr>
 
   <if queue>
     <assign grey="1">
     <list queue as q>
       <tr <if grey=="1">class="listrow1"<else>class="listrow2"</if>>
-        <td class="small">${q.factory}</td>
-        <td class="small">(${q.verb})</td>
+        <td class="small">${q.description}</td>
         
         <if q.status=="pending">
           <td class="text-alert small">${q.status}</td>
           <td class="small">${q.status}</td>
         </if>
         
-        <td class="small">${q.lastchange["HH:mm:ss"]}</td>
+        <td class="small">${q.lastchange.format("HH:mm:ss")}</td>
         <td class="small">${q.runningtime.format("####.#")}s</td>
-        <comment> ML: needs to be implemented       
-          <td><a href="${config.actionRoot}?module=Producer&do=abort">${lang("producer.job.cancel")}</a></td>
-        </comment>        
+        <td class="small">
+          <if q.finished!="1">
+            <input type="checkbox" name="jobid" value="${q.identifier}">
+          <else>
+            &nbsp;
+          </if>  
+        </td>
       </tr>
       <if grey=="1"><assign grey="0"><else><assign grey="1"></if>
     </list>
     </tr>
   </if>
   <tr>
-    <td colspan="5" class="table-foot">
+    <td colspan="5" class="table-foot" align="left">
       <br>
-      <a class="link-box"  href="${config.actionRoot}?${thisurl}">${lang("producer.jobqueue.refresh")}</a>
+      <input class="minorbutton" type="submit" value="${lang("producer.jobqueue.canceljobs")}">
     </td>
   </tr>
 </table>
+</form>
 
 </td></tr></table>
 
index 21c49a7..11908ba 100755 (executable)
@@ -182,3 +182,15 @@ a:hover            {
 
 .lynx            { display:none; }
 
+.majorbutton {
+}
+
+.minorbutton {
+       background-color:#DDDDDD; 
+       color: #990000;
+       font-size:1em;
+       padding:2px;
+       padding-left:8px;
+       padding-right:8px;
+//     border:1px solid #990000;  
+}