tiny fixes here and there
[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  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mircoders.global;
31
32 import mir.config.MirPropertiesConfiguration;
33 import mir.log.LoggerWrapper;
34 import mir.producer.Producer;
35 import mir.producer.ProducerFactory;
36 import mir.producer.ProductionContext;
37 import mir.util.GeneratorFormatAdapters;
38 import mir.util.StringRoutines;
39
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Collections;
46
47 public class ProducerEngine {
48   private final JobQueue producerJobQueue;
49   private final LoggerWrapper logger = new LoggerWrapper("Producer");
50   private final Map nameToFactory = new HashMap();;
51   private List factories = new ArrayList();
52
53   protected ProducerEngine() {
54     producerJobQueue = new JobQueue(new LoggerWrapper("Producer.Queue"));
55     reloadConfiguration();
56   }
57
58   /**
59    * Reloads the producer configuration
60    */
61   public void reloadConfiguration() {
62     try {
63       factories = new ArrayList(MirGlobal.localizer().producers().loadFactories());
64
65       synchronized (nameToFactory) {
66         nameToFactory.clear();
67
68         Iterator i = factories.iterator();
69         while (i.hasNext()) {
70           ProducerFactory factory = (ProducerFactory) i.next();
71           nameToFactory.put(factory.getName(), factory);
72         }
73       }
74     }
75     catch (Throwable t) {
76       throw new MirGlobalFailure(t);
77     }
78   }
79
80   /**
81    * Looks up a producer factory by name
82    */
83   private ProducerFactory getFactoryForName(String aName) {
84     synchronized (nameToFactory) {
85       return (ProducerFactory) nameToFactory.get(aName);
86     }
87   }
88
89   /**
90    * Returns all factories
91    */
92   public List getFactories() {
93     return Collections.unmodifiableList(factories);
94   }
95   /**
96    * Adds a producer job to the queue
97    */
98   public void addJob(String aProducerFactory, String aVerb) throws MirGlobalExc, MirGlobalFailure {
99     ProducerFactory factory = getFactoryForName( aProducerFactory );
100
101     if (factory==null) {
102       throw new MirGlobalExc("Unknown producer: " + aProducerFactory);
103     }
104
105     if (!factory.allowVerb(aVerb)) {
106       throw new MirGlobalExc("illegal producer/verb combination: " + aProducerFactory+"::"+aVerb);
107     }
108
109     producerJobQueue.appendJob(
110         new ProducerJob(aProducerFactory, aVerb), aProducerFactory+"."+aVerb);
111   }
112
113   /**
114    * Cancels a list of jobs by job identifier
115    */
116   public void cancelJobs(List aJobs) {
117     producerJobQueue.cancelJobs(aJobs);
118   }
119
120   /**
121    * Cancels all jobs in the queue
122    */
123   public void cancelAllJobs() {
124     producerJobQueue.cancelAllJobs();
125   }
126
127   public void addTask(ProducerTask aTask) throws MirGlobalExc, MirGlobalFailure {
128     addJob(aTask.getProducer(), aTask.getVerb());
129   }
130
131   private String convertStatus(JobQueue.JobInfo aJob) {
132
133     switch (aJob.getStatus()) {
134       case JobQueue.STATUS_ABORTED:
135         return "aborted";
136
137       case JobQueue.STATUS_CANCELLED:
138         return "cancelled";
139
140       case JobQueue.STATUS_CREATED:
141         return "created";
142
143       case JobQueue.STATUS_PENDING:
144         return "pending";
145
146       case JobQueue.STATUS_PROCESSED:
147         return "processed";
148
149       case JobQueue.STATUS_PROCESSING:
150         return "processing";
151     }
152
153     return "unknown";
154   }
155
156   private Map convertJob(JobQueue.JobInfo aJob) {
157     try {
158       Map result = new HashMap();
159
160       result.put("identifier", aJob.getIdentifier());
161       result.put("description", aJob.getDescription());
162       result.put("priority", new Integer(aJob.getPriority()));
163       result.put("runningtime", new Double( (double) aJob.getRunningTime() / 1000));
164       result.put("status", convertStatus(aJob));
165       result.put("lastchange", new GeneratorFormatAdapters.DateFormatAdapter(aJob.getLastChange(), MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone")));
166       result.put("finished", new Boolean(
167           aJob.getStatus() == JobQueue.STATUS_PROCESSED ||
168           aJob.getStatus() == JobQueue.STATUS_CANCELLED ||
169           aJob.getStatus() == JobQueue.STATUS_ABORTED));
170
171       return result;
172     }
173     catch (Throwable t) {
174       throw new RuntimeException(t.toString());
175     }
176   }
177
178   private List convertJobInfoList(List aJobInfoList) {
179     List result = new ArrayList();
180
181     Iterator i = aJobInfoList.iterator();
182
183     while (i.hasNext())
184       result.add(convertJob((JobQueue.JobInfo) i.next()));
185
186     return result;
187   }
188
189   public List getQueueStatus() {
190     return convertJobInfoList(producerJobQueue.getJobsInfo());
191   }
192
193   private class ProducerJob implements JobQueue.Job {
194     private String factoryName;
195     private String verb;
196     private Producer producer;
197     private ProductionContext productionContext;
198
199     ProducerJob(String aFactory, String aVerb) {
200       factoryName = aFactory;
201       verb = aVerb;
202       producer=null;
203     }
204
205     public String getFactoryName() {
206       return factoryName;
207     }
208
209     public String getVerb() {
210       return verb;
211     }
212
213     public void abort() {
214       if (producer!=null && productionContext!=null) {
215         producer.abort(productionContext);
216       }
217     }
218
219     public boolean run() {
220       final Map startingMap = new HashMap();
221
222       long startTime = System.currentTimeMillis();
223       logger.info("Producing job: "+factoryName+"."+verb);
224       boolean result = false;
225
226       try {
227         final ProducerFactory factory = getFactoryForName(factoryName);
228
229         if (factory!=null) {
230           MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(startingMap);
231
232           synchronized(factory) {
233             producer = factory.makeProducer(verb, startingMap);
234           }
235
236           if (producer!=null) {
237             try {
238               MirGlobal.localizer().producers().beforeProducerTask(factoryName, verb);
239             }
240             catch (Throwable t) {
241               logger.warn("Misbehaving beforeProducerTask",t );
242             }
243
244             productionContext = new ProductionContext() {
245               public ProducerFactory getFactory() {
246                 return factory;
247               }
248
249               public Producer getProducer() {
250                 return producer;
251               }
252
253               public String getVerb() {
254                 return verb;
255               }
256
257               public LoggerWrapper getLogger() {
258                 return logger;
259               }
260
261               public Map getValueSet() {
262                 return startingMap;
263               }
264             };
265
266             result = producer.execute(productionContext);
267             productionContext = null;
268             producer = null;
269
270             try {
271               MirGlobal.localizer().producers().afterProducerTask(factoryName, verb);
272             }
273             catch (Throwable t) {
274               logger.warn("Misbehaving afterProducerTask", t);
275             }
276           }
277         }
278       }
279       catch (Throwable t) {
280         logger.error("Exception occurred while producing " + factoryName + "." + verb, t);
281       }
282       long endTime = System.currentTimeMillis();
283
284       logger.info("Done producing job: " + factoryName + "." + verb + ", time elapsed:" + (endTime-startTime) + " ms");
285
286       return result;
287     }
288
289     boolean isAborted() {
290       return false;
291     }
292   }
293
294   public static class ProducerTask {
295     private String producer;
296     private String verb;
297
298     public ProducerTask(String aProducer, String aVerb) {
299       producer = aProducer;
300       verb = aVerb;
301     }
302
303     public String getVerb() {
304       return verb;
305     }
306
307     public String getProducer() {
308       return producer;
309     }
310
311     public static List parseProducerTaskList(String aList) throws MirGlobalExc {
312       List result = new ArrayList();
313
314       Iterator i = StringRoutines.splitString(aList, ";").iterator();
315       while (i.hasNext()) {
316         String taskExpression = ((String) i.next()).trim();
317
318         if (taskExpression.length()>0) {
319           List parts = StringRoutines.splitString(taskExpression, ".");
320
321           if (parts.size() != 2) {
322             throw new MirGlobalExc("Invalid producer expression: '" + taskExpression + "'");
323           }
324           result.add(new ProducerEngine.ProducerTask( (String) parts.get(0), (String) parts.get(1)));
325         }
326       }
327
328       return result;
329     }
330   }
331 }