log4j implemented for the producer subsystem
[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 import mir.log.*;
41
42 public class ProducerEngine {
43 //  private Map producers;
44   private JobQueue producerJobQueue;
45   private Thread queueThread;
46   private LoggerWrapper logger;
47
48
49   protected ProducerEngine() {
50     producerJobQueue = new JobQueue();
51     logger = new LoggerWrapper("producer");
52
53     queueThread = new Thread(new ProducerJobQueueThread());
54     queueThread.start();
55   }
56
57   public void addJob(String aProducerFactory, String aVerb) {
58     producerJobQueue.appendJob(new ProducerJob(aProducerFactory, aVerb));
59   }
60
61   public void addTask(ProducerTask aTask) {
62     addJob(aTask.getProducer(), aTask.getVerb());
63   }
64
65   public void addTasks(List aTasks) {
66     Iterator i = aTasks.iterator();
67
68     while (i.hasNext()) {
69       addTask((ProducerTask) i.next());
70     }
71   }
72
73   private String convertStatus(JobQueue.Job aJob) {
74     if (aJob.hasBeenProcessed())
75       return "processed";
76     if (aJob.isProcessing())
77       return "processing";
78     if (aJob.isPending())
79       return "pending";
80     if (aJob.isCancelled())
81       return "cancelled";
82     if (aJob.hasBeenAborted())
83       return "aborted";
84
85     return "unknown";
86   }
87
88   private Map convertJob(JobQueue.Job aJob) {
89     Map result = new HashMap();
90     ProducerJob producerJob = (ProducerJob) aJob.getData();
91
92     result.put("identifier", aJob.getIdentifier());
93     result.put("factory", producerJob.getFactoryName());
94     result.put("verb", producerJob.getVerb());
95     result.put("priority", new Integer(aJob.getPriority()));
96     result.put("status", convertStatus(aJob));
97     result.put("lastchange", new DateToMapAdapter(aJob.getLastChange()));
98
99     return result;
100   }
101
102   private void convertJobList(List aSourceJobList, List aDestination) {
103     Iterator i = aSourceJobList.iterator();
104
105     while (i.hasNext())
106       aDestination.add(convertJob((JobQueue.Job) i.next()));
107   }
108
109   public List getQueueStatus() {
110     List result = new Vector();
111     List pendingJobs = new Vector();
112     List finishedJobs = new Vector();
113
114     producerJobQueue.makeJobListSnapshots(pendingJobs, finishedJobs);
115
116     convertJobList(pendingJobs, result);
117     convertJobList(finishedJobs, result);
118
119     return result;
120   }
121
122 private class ProducerJob {
123     private String factoryName;
124     private String verb;
125     private Producer producer;
126
127     public ProducerJob(String aFactory, String aVerb) {
128       factoryName = aFactory;
129       verb = aVerb;
130       producer=null;
131     }
132
133     public String getFactoryName() {
134       return factoryName;
135     }
136
137     public String getVerb() {
138       return verb;
139     }
140
141     public void abort() {
142       if (producer!=null) {
143         producer.abort();
144       }
145     }
146
147     public void execute() {
148       ProducerFactory factory;
149       long startTime;
150       long endTime;
151       Map startingMap = new HashMap();
152
153       startTime = System.currentTimeMillis();
154       logger.info("Producing job: "+factoryName+"."+verb);
155
156       try {
157         factory = MirGlobal.localizer().producers().getFactoryForName( factoryName );
158
159         if (factory!=null) {
160           MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(startingMap);
161
162           synchronized(factory) {
163             producer = factory.makeProducer(verb, startingMap);
164           }
165           if (producer!=null) {
166             producer.produce(logger);
167           }
168         }
169       }
170       catch (Throwable t) {
171         logger.error("Exception occurred while producing " + factoryName + "." + verb + t.getMessage());
172         t.printStackTrace(new PrintWriter(new LoggerToWriterAdapter(logger, LoggerWrapper.ERROR_MESSAGE)));
173       }
174       endTime = System.currentTimeMillis();
175       logger.info("Done producing job: " + factoryName + "." + verb + ", time elapsed:" + (endTime-startTime) + " ms");
176     }
177
178     boolean isAborted() {
179       return false;
180     }
181   }
182
183   private class ProducerJobQueueThread implements Runnable {
184     public void run() {
185       logger.debug("starting ProducerJobQueueThread");
186
187       while (true) {
188         ProducerJob job = (ProducerJob) producerJobQueue.acquirePendingJob();
189         if (job!=null) {
190           job.execute();
191           if (job.isAborted())
192             producerJobQueue.jobAborted(job);
193           else
194             producerJobQueue.jobProcessed(job);
195         }
196         else
197         {
198           try {
199             Thread.sleep(1500);
200           }
201           catch (InterruptedException e) {
202           }
203         }
204       }
205     }
206   }
207
208   public static class ProducerEngineExc extends Exc {
209     public ProducerEngineExc(String aMessage) {
210       super(aMessage);
211     }
212   }
213
214   public static class ProducerEngineRuntimeExc extends Failure {
215     public ProducerEngineRuntimeExc(String msg, Exception cause){
216       super(msg,cause);
217     }
218   }
219
220   public static class ProducerTask {
221     private String producer;
222     private String verb;
223
224     public ProducerTask(String aProducer, String aVerb) {
225       producer = aProducer;
226       verb = aVerb;
227     }
228
229     public String getVerb() {
230       return verb;
231     }
232
233     public String getProducer() {
234       return producer;
235     }
236
237     public static List parseProducerTaskList(String aList) throws ProducerEngineExc {
238       Iterator i;
239       List result = new Vector();
240
241       i = StringRoutines.splitString(aList, ";").iterator();
242       while (i.hasNext()) {
243         String taskExpression = (String) i.next();
244         List parts = StringRoutines.splitString(taskExpression, ".");
245
246         if (parts.size()!=2)
247           throw new ProducerEngineExc("Invalid producer expression: '" + taskExpression + "'");
248         else
249           result.add(new ProducerEngine.ProducerTask((String) parts.get(0), (String) parts.get(1)));
250       }
251
252       return result;
253     }
254   }
255 }