20bbc5e3fc6d79e7ee9ce0c94101558ccc510507
[mir.git] / source / mircoders / global / ProducerEngine.java
1 /*
2  * Copyright (C) 2001, 2002  The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with the com.oreilly.servlet library, any library
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24  * the above that use the same license as the above), and distribute linked
25  * combinations including the two.  You must obey the GNU General Public
26  * License in all respects for all of the code used other than the above
27  * mentioned libraries.  If you modify this file, you may extend this exception
28  * to your version of the file, but you are not obligated to do so.  If you do
29  * not wish to do so, delete this exception statement from your version.
30  */
31
32 package mircoders.global;
33
34 import java.util.*;
35 import java.io.*;
36 import mir.producer.*;
37 import mir.util.*;
38 import multex.Exc;
39 import multex.Failure;
40
41 public class ProducerEngine {
42 //  private Map producers;
43   private JobQueue producerJobQueue;
44   private Thread queueThread;
45   private PrintWriter log;
46
47   protected ProducerEngine() {
48     producerJobQueue = new JobQueue();
49     try {
50       RandomAccessFile raFile = (new RandomAccessFile(MirGlobal.getConfigProperty("Home") + "/" + MirGlobal.getConfigProperty("Producer.Logfile"), "rw"));
51                         raFile.seek(raFile.length());
52                 log = new PrintWriter(new FileWriter( raFile.getFD()));
53     }
54     catch (Exception e) {
55       log = new PrintWriter(new NullWriter());
56     }
57     queueThread = new Thread(new ProducerJobQueueThread());
58     queueThread.start();
59   }
60
61   public void addJob(String aProducerFactory, String aVerb) {
62     producerJobQueue.appendJob(new ProducerJob(aProducerFactory, aVerb));
63     log.println(aProducerFactory+"."+aVerb+" added to queue");
64     log.flush();
65   }
66
67   public void addTask(ProducerTask aTask) {
68     addJob(aTask.getProducer(), aTask.getVerb());
69   }
70
71   public void addTasks(List aTasks) {
72     Iterator i = aTasks.iterator();
73
74     while (i.hasNext()) {
75       addTask((ProducerTask) i.next());
76     }
77   }
78
79   private String convertStatus(JobQueue.Job aJob) {
80     if (aJob.hasBeenProcessed())
81       return "processed";
82     if (aJob.isProcessing())
83       return "processing";
84     if (aJob.isPending())
85       return "pending";
86     if (aJob.isCancelled())
87       return "cancelled";
88     if (aJob.hasBeenAborted())
89       return "aborted";
90
91     return "unknown";
92   }
93
94   private Map convertJob(JobQueue.Job aJob) {
95     Map result = new HashMap();
96     ProducerJob producerJob = (ProducerJob) aJob.getData();
97
98     result.put("identifier", aJob.getIdentifier());
99     result.put("factory", producerJob.getFactoryName());
100     result.put("verb", producerJob.getVerb());
101     result.put("priority", new Integer(aJob.getPriority()));
102     result.put("status", convertStatus(aJob));
103     result.put("lastchange", new DateToMapAdapter(aJob.getLastChange()));
104
105     return result;
106   }
107
108   private void convertJobList(List aSourceJobList, List aDestination) {
109     Iterator i = aSourceJobList.iterator();
110
111     while (i.hasNext())
112       aDestination.add(convertJob((JobQueue.Job) i.next()));
113   }
114
115   public List getQueueStatus() {
116     List result = new Vector();
117     List pendingJobs = new Vector();
118     List finishedJobs = new Vector();
119
120     producerJobQueue.makeJobListSnapshots(pendingJobs, finishedJobs);
121
122     convertJobList(pendingJobs, result);
123     convertJobList(finishedJobs, result);
124
125     return result;
126   }
127
128 private class ProducerJob {
129     private String factoryName;
130     private String verb;
131     private Producer producer;
132
133     public ProducerJob(String aFactory, String aVerb) {
134       factoryName = aFactory;
135       verb = aVerb;
136       producer=null;
137     }
138
139     public String getFactoryName() {
140       return factoryName;
141     }
142
143     public String getVerb() {
144       return verb;
145     }
146
147     public void abort() {
148       if (producer!=null) {
149         producer.abort();
150       }
151     }
152
153     public void execute() {
154       ProducerFactory factory;
155       long startTime;
156       long endTime;
157       Map startingMap = new HashMap();
158
159       startTime = System.currentTimeMillis();
160       log.println("Producing job: "+factoryName+"."+verb);
161
162       try {
163         factory = MirGlobal.localizer().producers().getFactoryForName( factoryName );
164
165         if (factory!=null) {
166           MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(startingMap);
167
168           synchronized(factory) {
169             producer = factory.makeProducer(verb, startingMap);
170           }
171           if (producer!=null) {
172             producer.produce(log);
173           }
174         }
175       }
176       catch (Throwable t) {
177         log.println("  exception "+t.getMessage());
178         t.printStackTrace(log);
179       }
180       log.println("Done producing job: "+factoryName+"."+verb);
181       endTime = System.currentTimeMillis();
182       log.println("Time: " + (endTime-startTime) + " ms");
183       log.flush();
184     }
185
186     boolean isAborted() {
187       return false;
188     }
189   }
190
191   private class ProducerJobQueueThread implements Runnable {
192     public void run() {
193       log.println("starting ProducerJobQueueThread");
194       log.flush();
195
196       while (true) {
197         ProducerJob job = (ProducerJob) producerJobQueue.acquirePendingJob();
198         if (job!=null) {
199           job.execute();
200           if (job.isAborted())
201             producerJobQueue.jobAborted(job);
202           else
203             producerJobQueue.jobProcessed(job);
204         }
205         else
206         {
207           try {
208             Thread.sleep(1500);
209           }
210           catch (InterruptedException e) {
211           }
212         }
213       }
214     }
215   }
216
217   public static class ProducerEngineExc extends Exc {
218     public ProducerEngineExc(String aMessage) {
219       super(aMessage);
220     }
221   }
222
223   public static class ProducerEngineRuntimeExc extends Failure {
224     public ProducerEngineRuntimeExc(String msg, Exception cause){
225       super(msg,cause);
226     }
227   }
228
229   public static class ProducerTask {
230     private String producer;
231     private String verb;
232
233     public ProducerTask(String aProducer, String aVerb) {
234       producer = aProducer;
235       verb = aVerb;
236     }
237
238     public String getVerb() {
239       return verb;
240     }
241
242     public String getProducer() {
243       return producer;
244     }
245
246     public static List parseProducerTaskList(String aList) throws ProducerEngineExc {
247       Iterator i;
248       List result = new Vector();
249
250       i = StringRoutines.splitString(aList, ";").iterator();
251       while (i.hasNext()) {
252         String taskExpression = (String) i.next();
253         List parts = StringRoutines.splitString(taskExpression, ".");
254
255         if (parts.size()!=2)
256           throw new ProducerEngineExc("Invalid producer expression: '" + taskExpression + "'");
257         else
258           result.add(new ProducerEngine.ProducerTask((String) parts.get(0), (String) parts.get(1)));
259       }
260
261       return result;
262     }
263   }
264 }