1.1 restoration
[mir.git] / source / mircoders / global / ProducerEngine.java
index 128a947..33a6267 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001, 2002  The Mir-coders group
+ * Copyright (C) 2001, 2002 The Mir-coders group
  *
  * This file is part of Mir.
  *
  * 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 the com.oreilly.servlet library, 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.
+ * 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 mircoders.global;
 
-import java.util.*;
-import java.io.*;
-import mir.producer.*;
-import mir.util.*;
-import multex.Exc;
-import multex.Failure;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import mir.config.MirPropertiesConfiguration;
+import mir.log.LoggerToWriterAdapter;
+import mir.log.LoggerWrapper;
+import mir.producer.Producer;
+import mir.producer.ProducerFactory;
+import mir.util.GeneratorFormatAdapters;
+import mir.util.StringRoutines;
 
 public class ProducerEngine {
-//  private Map producers;
   private JobQueue producerJobQueue;
-  private Thread queueThread;
-  private PrintWriter log;
+  private LoggerWrapper logger;
+  private Map nameToFactory;
+  private List factories;
 
   protected ProducerEngine() {
-//    producers = MirGlobal.localizer().producers().factories();
-    producerJobQueue = new JobQueue();
+    logger = new LoggerWrapper("Producer");
+    producerJobQueue = new JobQueue(new LoggerWrapper("Producer.Queue"));
+
+    factories = new ArrayList();
+    nameToFactory = new HashMap();
+
     try {
-      RandomAccessFile raFile = (new RandomAccessFile(MirGlobal.getConfigProperty("Home") + "/" + MirGlobal.getConfigProperty("Producer.Logfile"), "rw"));
-                        raFile.seek(raFile.length());
-                log = new PrintWriter(new FileWriter( raFile.getFD()));
+      reloadConfiguration();
     }
-    catch (Exception e) {
-//      throw new ProducerEngineRuntimeExc("Creating PrintWriter log failed",e);
-      log = new PrintWriter(new NullWriter());
+    catch (Throwable t) {
     }
-    queueThread = new Thread(new ProducerJobQueueThread());
-    queueThread.start();
   }
 
-  public void addJob(String aProducerFactory, String aVerb) {
-    producerJobQueue.appendJob(new ProducerJob(aProducerFactory, aVerb));
-    log.println(aProducerFactory+"."+aVerb+" added to queue");
-    log.flush();
-  }
+  /**
+   * Reloads the producer configuration
+   */
+  public void reloadConfiguration()  throws MirGlobalExc, MirGlobalFailure {
+    try {
+      factories = MirGlobal.localizer().producers().loadFactories();
 
-  public void addTask(ProducerTask aTask) {
-    addJob(aTask.getProducer(), aTask.getVerb());
-  }
+      synchronized (nameToFactory) {
+        nameToFactory.clear();
 
-  public void addTasks(List aTasks) {
-    Iterator i = aTasks.iterator();
+        Iterator i = factories.iterator();
+        while (i.hasNext()) {
+          ProducerFactory factory = (ProducerFactory) i.next();
+          nameToFactory.put(factory.getName(), factory);
+        }
+      }
+    }
+    catch (Throwable t) {
+      throw new MirGlobalFailure(t);
+    }
+  }
 
-    while (i.hasNext()) {
-      addTask((ProducerTask) i.next());
+  /**
+   * Looks up a producer factory by name
+   */
+  private ProducerFactory getFactoryForName(String aName) {
+    synchronized (nameToFactory) {
+      return (ProducerFactory) nameToFactory.get(aName);
     }
   }
 
-  public void printQueueStatus(PrintWriter aWriter) {
-    Iterator iterator = producerJobQueue.makeJobListSnapshot().iterator();
-    producerJobQueue.cleanupJobs();
-    JobQueue.Job job;
+  /**
+   * Returns all factories
+   */
+  public List getFactories() {
+    return factories;
+  }
+  /**
+   * Adds a producer job to the queue
+   */
+  public void addJob(String aProducerFactory, String aVerb) throws MirGlobalExc, MirGlobalFailure {
+    ProducerFactory factory;
 
-    while (iterator.hasNext()) {
-      job = (JobQueue.Job) iterator.next();
-      ProducerJob producerJob = (ProducerJob) job.getData();
+    factory = getFactoryForName( aProducerFactory );
 
-      aWriter.print(producerJob.factoryName + "." + producerJob.verb);
-      if (job.hasBeenProcessed())
-        aWriter.print(" processed");
-      else if (job.isProcessing())
-        aWriter.print(" processing");
-      else if (job.isPending())
-        aWriter.print(" pending");
-      else
-        aWriter.print(" unknown status");
+    if (factory==null)
+      throw new MirGlobalExc("Unknown producer: " + aProducerFactory);
 
-      aWriter.println("<br/>");
-    }
-  }
+    if (!factory.allowVerb(aVerb))
+      throw new MirGlobalExc("illegal producer/verb combination: " + aProducerFactory+"::"+aVerb);
 
-  private void produceNow(String aProducerFactory, String aVerb, PrintWriter aLogger) {
-    try {
-      long startTime;
-      long endTime;
-      Map startingMap = new HashMap();
+    producerJobQueue.appendJob(
+        new ProducerJob(aProducerFactory, aVerb), aProducerFactory+"."+aVerb);
+  }
 
-      startTime = System.currentTimeMillis();
+  /**
+   * Cancels a list of jobs by job identifier
+   */
+  public void cancelJobs(List aJobs) {
+    producerJobQueue.cancelJobs(aJobs);
+  };
+
+  /**
+   * Cancels all jobs in the queue
+   */
+  public void cancelAllJobs() {
+    producerJobQueue.cancelAllJobs();
+  };
+
+  public void addTask(ProducerTask aTask) throws MirGlobalExc, MirGlobalFailure {
+    addJob(aTask.getProducer(), aTask.getVerb());
+  }
 
-      aLogger.println("Producing (" + aProducerFactory + "," + aVerb + ")");
+  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";
+  }
 
-      ProducerFactory factory = (ProducerFactory) MirGlobal.localizer().producers().factories().get(aProducerFactory);
+  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));
+
+      return result;
+    }
+    catch (Throwable t) {
+      throw new RuntimeException(t.toString());
+    }
+  }
 
-      if (factory == null )
-        throw new Exception("No producer factory '"+aProducerFactory+"' present.");
+  private List convertJobInfoList(List aJobInfoList) {
+    List result = new Vector();
 
-      MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(startingMap);
-      Producer producer = factory.makeProducer(aVerb, startingMap);
+    Iterator i = aJobInfoList.iterator();
 
-      producer.produce(aLogger);
+    while (i.hasNext())
+      result.add(convertJob((JobQueue.JobInfo) i.next()));
 
-      endTime = System.currentTimeMillis();
+    return result;
+  }
 
-      aLogger.println("Time: " + (endTime-startTime) + " ms<br>");
-    }
-    catch (Throwable e) {
-      try {
-        aLogger.println("exception occurred:<br>");
-        aLogger.println(e.getMessage());
-        e.printStackTrace(aLogger);
-      }
-      catch (Throwable f) {
-      }
-    }
+  public List getQueueStatus() {
+    return convertJobInfoList(producerJobQueue.getJobsInfo());
   }
 
-  private class ProducerJob {
+  private class ProducerJob implements JobQueue.Job {
     private String factoryName;
     private String verb;
+    private Producer producer;
 
     public ProducerJob(String aFactory, String aVerb) {
       factoryName = aFactory;
       verb = aVerb;
+      producer=null;
+    }
+
+    public String getFactoryName() {
+      return factoryName;
+    }
+
+    public String getVerb() {
+      return verb;
     }
 
-    public void execute() {
+    public void abort() {
+      if (producer!=null) {
+        producer.abort();
+      }
+    }
+
+    public boolean run() {
       ProducerFactory factory;
-      Producer producer;
       long startTime;
       long endTime;
+      boolean result = false;
       Map startingMap = new HashMap();
+      Map mirMap = new HashMap();
+      mirMap.put("producer", factoryName);
+      mirMap.put("verb", verb);
+
+      startingMap.put("Mir", mirMap);
 
       startTime = System.currentTimeMillis();
-      log.println("Producing job: "+factoryName+"."+verb);
+      logger.info("Producing job: "+factoryName+"."+verb);
 
       try {
-        factory = (ProducerFactory) MirGlobal.localizer().producers().factories().get( factoryName );
+        factory = getFactoryForName(factoryName);
 
         if (factory!=null) {
           MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(startingMap);
@@ -165,49 +242,22 @@ public class ProducerEngine {
             producer = factory.makeProducer(verb, startingMap);
           }
           if (producer!=null) {
-            producer.produce(log);
+            result = producer.produce(logger);
           }
         }
       }
       catch (Throwable t) {
-        log.println("  exception "+t.getMessage());
-        t.printStackTrace(log);
+        logger.error("Exception occurred while producing " + factoryName + "." + verb + t.getMessage());
+        t.printStackTrace(new PrintWriter(new LoggerToWriterAdapter(logger, LoggerWrapper.ERROR_MESSAGE)));
       }
-      log.println("Done producing job: "+factoryName+"."+verb);
-                  endTime = System.currentTimeMillis();
-
-                  log.println("Time: " + (endTime-startTime) + " ms");
-                  log.flush();
-    }
-  }
-
-  private class ProducerJobQueueThread implements Runnable {
-    public void run() {
-      log.println("starting ProducerJobQueueThread");
-      log.flush();
+      endTime = System.currentTimeMillis();
+      logger.info("Done producing job: " + factoryName + "." + verb + ", time elapsed:" + (endTime-startTime) + " ms");
 
-      while (true) {
-        ProducerJob job = (ProducerJob) producerJobQueue.acquirePendingJob();
-        if (job!=null) {
-          job.execute();
-          producerJobQueue.flagOffJob(job);
-        }
-        else
-        {
-          try {
-            Thread.sleep(1500);
-          }
-          catch (InterruptedException e) {
-          }
-        }
-      }
+      return result;
     }
-  }
-
 
-  public static class ProducerEngineRuntimeExc extends Failure {
-    public ProducerEngineRuntimeExc(String msg, Exception cause){
-      super(msg,cause);
+    boolean isAborted() {
+      return false;
     }
   }
 
@@ -227,5 +277,26 @@ public class ProducerEngine {
     public String getProducer() {
       return producer;
     }
+
+    public static List parseProducerTaskList(String aList) throws MirGlobalExc {
+      Iterator i;
+      List result = new Vector();
+
+      i = StringRoutines.splitString(aList, ";").iterator();
+      while (i.hasNext()) {
+        String taskExpression = ((String) i.next()).trim();
+
+        if (taskExpression.length()>0) {
+          List parts = StringRoutines.splitString(taskExpression, ".");
+
+          if (parts.size() != 2)
+            throw new MirGlobalExc("Invalid producer expression: '" + taskExpression + "'");
+          else
+            result.add(new ProducerEngine.ProducerTask( (String) parts.get(0), (String) parts.get(1)));
+        }
+      }
+
+      return result;
+    }
   }
 }
\ No newline at end of file