changes for tomcat 4.1.x also compatible with 4.0.x, mir/servlet/Mir becomes /mir...
[mir.git] / source / mir / misc / HTMLTemplateProcessor.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 mir.misc;
33
34 import  java.lang.*;
35 import  java.util.*;
36 import  java.io.*;
37 import  java.net.*;
38 import  freemarker.template.*;
39 import  mir.entity.*;
40 import  mir.storage.*;
41 import javax.servlet.http.*;
42 import org.apache.struts.util.MessageResources;
43
44
45 /**
46  * Hilfsklasse zum Mergen von Template und Daten
47  */
48 public final class HTMLTemplateProcessor {
49
50   public static String                templateDir;
51   private static FileTemplateCache    templateCache;
52   private static Logfile              theLog;
53   private static String               docRoot;
54   private static String               actionRoot;
55   private static String               productionHost;
56   private static String               audioHost;
57   private static String               videoHost;
58   private static String               imageHost;
59   private static String               imagePath;
60   private static String               openAction;
61   private static String               defEncoding;
62   private static String               generateFO;
63   private static String               generatePDF;
64   protected static String producerDocRoot =
65                 MirConfig.getProp("Producer.DocRoot");
66   protected static String producerStorageRoot =
67                 MirConfig.getProp("Producer.StorageRoot");
68
69   //
70   // init
71
72   static {
73     /** @todo either in the above block or here :) //rk */
74     templateDir = MirConfig.getPropWithHome("HTMLTemplateProcessor.Dir");
75     templateCache = new FileTemplateCache(templateDir);
76     templateCache.setLoadingPolicy(templateCache.LOAD_ON_DEMAND);
77     // gone in freemarker 1.7.1
78     // templateCache.startAutoUpdate();
79     theLog = Logfile.getInstance(MirConfig.getPropWithHome("HTMLTemplateProcessor.Logfile"));
80     docRoot = MirConfig.getProp("RootUri");
81     //the quick hack is back in effect as it was more broken than ever before
82     // -mh
83     // sorry: nadir back in town, i have to debug the mirbase.jar in the
84     // nadir evironment. from my point of coding, this needs an urgent
85     // fixxx.
86     // yeah, from my point too - tob.
87           //actionRoot = docRoot + "/servlet/" + MirConfig.getProp("ServletName");
88     //actionRoot = docRoot + "/servlet/NadirAktuell";
89
90     actionRoot = docRoot + "/Mir";
91
92     defEncoding = MirConfig.getProp("Mir.DefaultEncoding");
93     openAction = MirConfig.getProp("Producer.OpenAction");
94     productionHost = MirConfig.getProp("Producer.ProductionHost");
95     videoHost = MirConfig.getProp("Producer.VideoHost");
96     audioHost = MirConfig.getProp("Producer.AudioHost");
97     imageHost = MirConfig.getProp("Producer.Image.Host");
98     imagePath = MirConfig.getProp("Producer.Image.Path");
99     producerDocRoot = MirConfig.getProp("Producer.DocRoot");
100     producerStorageRoot = MirConfig.getProp("Producer.StorageRoot");
101     generateFO = MirConfig.getProp("GenerateFO");
102     generatePDF = MirConfig.getProp("GeneratePDF");
103   }
104
105   /**
106    * empty private constructor, to avoid instantiation
107    */
108   private HTMLTemplateProcessor () { }
109
110
111   // process-methods to merge different datastructures
112   // with freemarker templates
113
114
115   /**
116    * Wandelt <code>anEntity</code> in freemarker-Struktur um, mischt die Daten mit
117    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
118    * <code>out</code>
119    *
120    * @param templateFilename
121    * @param anEntity
122    * @param out
123    * @exception HTMLParseException
124    */
125
126     public static void process(String templateFilename, Entity anEntity, PrintWriter out)
127       throws HTMLParseException {
128         if (anEntity == null)  throw new HTMLParseException("entity is empty!");
129         else process(templateFilename, anEntity, out);
130     }
131
132
133   /**
134    * Wandelt Liste mit Entities <code>entList</code> in freemarker-Struktur um, mischt die Daten mit
135    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
136    * <code>out</code>
137    *
138    * @param templateFilename
139    * @param entList
140    * @param out
141    * @exception HTMLParseException
142    */
143   public static void process(HttpServletResponse res,String templateFilename,
144                                                                                                                  EntityList entList, PrintWriter out, Locale locale)
145     throws HTMLParseException {
146     process(res, templateFilename, entList, (String)null, (TemplateModelRoot)null, out, locale);
147   }
148
149   /**
150    * Wandelt Entitylist in freemarker-Struktur um, fügt <code>additionalModel</code>
151    * unter dem Namen <code>additionalModelName</code> ein und mischt die Daten mit
152    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
153    * <code>out</code>
154    *
155    * @param templateFilename
156    * @param entList
157    * @param additionalModelName
158    * @param additionalModel
159    * @param out
160    * @exception HTMLParseException
161    */
162     public static void process(HttpServletResponse res,String templateFilename,
163                                                                                                                          EntityList entList, String additionalModelName,
164                                TemplateModelRoot additionalModel, PrintWriter out,
165                                                                                                                          Locale locale)
166       throws HTMLParseException {
167
168       SimpleHash modelRoot = new SimpleHash();
169
170       if (entList == null) {
171          process(null,templateFilename, modelRoot, out, locale);
172       } else {
173         try {
174           modelRoot = makeSimpleHashWithEntitylistInfos(entList);
175
176           // Quickhack um mal ein Popup mit reinzunhemen ..
177           if (additionalModelName != null && additionalModel != null)
178               modelRoot.put(additionalModelName, additionalModel);
179
180           process(res,templateFilename, modelRoot, out, locale);
181         } catch (StorageObjectException e) {
182           throw new HTMLParseException(e.toString());
183         }
184       }
185     }
186
187   /**
188    * Wandelt HashMap <code>mergeData</code> in freemarker-Struktur und mischt diese mit
189    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
190    * <code>out</code>
191    *
192    * @param templateFilename
193    * @param mergeData - a HashMap with mergeData to be converted in SimpleHash
194    * @param out
195    * @exception HTMLParseException
196    */
197     public static void process(HttpServletResponse res,String templateFilename,
198                                                                                                                          HashMap mergeData, PrintWriter out, Locale locale)
199       throws HTMLParseException {
200       process(res,templateFilename, makeSimpleHash(mergeData), out, locale);
201     }
202
203   /**
204    * Gibt Template <code>templateFilename</code> an den PrintWriter
205    * <code>out</code>
206    *
207    * @param templateFilename
208    * @param mergeData
209    * @param out
210    * @exception HTMLParseException
211    */
212     public static void process(String templateFilename, PrintWriter out,
213                                                                                                                          Locale locale)
214       throws HTMLParseException {
215       process(null,templateFilename, (TemplateModelRoot)null, out, locale);
216     }
217
218
219         /**
220    * Mischt die freemarker-Struktur <code>tmr</code> mit
221    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
222    * <code>out</code>
223    *
224    * @param templateFilename
225    * @param mergeData
226    * @param out
227    * @exception HTMLParseException
228    */
229         public static void process(HttpServletResponse res,String templateFilename,
230                                                                                                                  TemplateModelRoot tmr, PrintWriter out, Locale locale)
231         throws HTMLParseException {
232                 process(res,templateFilename,tmr,null,out,locale);
233
234         }
235
236   /**
237    * Mischt die freemarker-Struktur <code>tmr</code> mit
238    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
239    * <code>out</code>
240    *
241    * @param templateFilename
242    * @param mergeData
243    * @param out
244    * @exception HTMLParseException
245    */
246         public static void process(HttpServletResponse res,String templateFilename,
247                                                                                                                  TemplateModelRoot tmr, TemplateModelRoot extra,
248                                                                                                                  PrintWriter out, Locale locale)
249                 throws HTMLParseException {
250                 if (out==null) throw new HTMLParseException("no outputstream");
251                 Template tmpl = getTemplateFor(templateFilename);
252                 if (tmpl == null) throw new HTMLParseException("no template: " + templateFilename);
253                 if (tmr==null) tmr = new SimpleHash();
254
255                 /** @todo  what is this for? (rk) */
256                 String session="";
257                 if (res!=null) {
258                         session=res.encodeURL("");
259                 }
260
261     // @todo wouldn't it be so much easier to just pass the whole damn config
262     // Hash here from Mirconfig... ??????? than we could access arbitrary config
263     // values in the templates. -mh
264                 // put standard configuration into tempalteRootmodel
265                 SimpleHash configHash = new SimpleHash();
266                 configHash.put("defEncoding", new SimpleScalar(defEncoding));
267                 configHash.put("producerDocRoot", new SimpleScalar(producerDocRoot));
268                 configHash.put("storageRoot", new SimpleScalar(producerStorageRoot));
269     configHash.put("productionHost", new SimpleScalar(productionHost));
270                 configHash.put("openAction", new SimpleScalar(openAction));
271                 configHash.put("actionRootLogin",new SimpleScalar(actionRoot));
272                 configHash.put("docRoot", new SimpleScalar(docRoot));
273                 configHash.put("now", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
274                 configHash.put("actionRoot", new SimpleScalar(actionRoot+session));
275                 configHash.put("videoHost", new SimpleScalar(videoHost));
276                 configHash.put("audioHost", new SimpleScalar(audioHost));
277                 configHash.put("imageHost", new SimpleScalar(imageHost));
278                 configHash.put("imagePath", new SimpleScalar(imagePath));
279                 configHash.put("mirVersion", new SimpleScalar(MirConfig.getProp("Mir.Version")));
280                 // this conform to updated freemarker syntax
281                 configHash.put("compressWhitespace", new freemarker.template.utility.CompressWhitespace() );
282                 configHash.put("generateFO", new SimpleScalar(generateFO));
283                 configHash.put("generatePDF", new SimpleScalar(generatePDF));
284
285                 SimpleHash outPutHash = new SimpleHash();
286
287                 if(extra!=null){
288                         outPutHash.put("extra",extra);
289                         try{
290                         while(((SimpleList)extra).hasNext()){
291                                 theLog.printDebugInfo(((SimpleList)extra).next().toString());
292                         }
293                         }catch(Exception e){}
294                 }
295                 outPutHash.put("data",tmr);
296                 outPutHash.put("config", configHash);
297
298                 MessageResources messages = MessageResources.getMessageResources("bundles.admin");
299                 outPutHash.put("lang", new MessageMethodModel(locale, messages) );
300
301                 tmpl.process(outPutHash,out);
302         }
303
304
305   /**
306    *   Converts Entity-List to SimpleList of SimpleHashes.
307    *   @param aList ist eine Liste von Entity
308    *   @return eine freemarker.template.SimpleList von SimpleHashes.
309    *
310    *    @deprecated EntityLists comply with TemplateListModel now.
311    */
312   public static SimpleList makeSimpleList(EntityList aList) throws StorageObjectException
313   {
314     theLog.printWarning("## using deprecated makeSimpleList(entityList) - a waste of resources");
315     SimpleList  simpleList = new SimpleList();
316     if (aList != null) {
317       for(int i=0;i<aList.size();i++) {
318         simpleList.add(aList.elementAt(i));
319       }
320     }
321     return simpleList;
322   }
323
324   /**
325    *  Konvertiert ein EntityList in ein freemarker.template.SimpleHash-Modell. Im Hash
326    *  sind die einzelnen Entities ueber ihre id zu erreichen.
327    *  @param aList ist die EntityList
328    *  @return SimpleHash mit den entsprechenden freemarker Daten
329    *
330    */
331   public static SimpleHash makeSimpleHash(EntityList aList) throws StorageObjectException
332   {
333     SimpleHash      simpleHash = new SimpleHash();
334     Entity          currentEntity;
335
336     if (aList != null) {
337       for (int i=0;i<aList.size();i++) {
338          currentEntity = (Entity)aList.elementAt(i);
339          simpleHash.put(currentEntity.getId(), currentEntity);
340       }
341     }
342     return simpleHash;
343   }
344
345   /**
346    *  Konvertiert ein Entity in ein freemarker.template.SimpleHash-Modell
347    *  @param entity ist die Entity
348    *  @return SimpleHash mit den entsprechenden freemarker Daten
349    *
350    *  @deprecated This method is deprecated and will be deleted in the next
351    *  release. Entity interfaces freemarker.template.TemplateHashModel now
352    *  and can be used in the same way as SimpleHash. It is not necessary any
353    *  more to make a SimpleHash from an Entity
354    */
355   public static SimpleHash makeSimpleHash(Entity entity) {
356     if (entity != null) {
357       theLog.printWarning("## using deprecated makeSimpleHash(entity) - a waste of resources");
358       return makeSimpleHash(entity.getValues());
359     }
360     else
361       return null;
362   }
363
364   /**
365    *  Konvertiert ein Hashtable mit den keys und values als String
366    *  in ein freemarker.template.SimpleHash-Modell
367    *  @param mergeData der HashMap mit den String / String Daten
368    *  @return SimpleHash mit den entsprechenden freemarker Daten
369    *
370    */
371   public static SimpleHash makeSimpleHash(HashMap mergeData)
372   {
373     SimpleHash modelRoot = new SimpleHash();
374     String aField;
375     if (mergeData != null) {
376       Set set = mergeData.keySet();
377       Iterator it =  set.iterator();
378       for (int i=0; i<set.size();i++)  {
379         aField = (String)it.next();
380         modelRoot.put(aField, (String)mergeData.get(aField));
381       }
382     }
383     return modelRoot;
384   }
385
386
387   /**
388    * Converts EntityList in SimpleHash and adds additional information
389    * to the returned SimpleHash
390    *
391    * @param entList
392    * @return SimpleHash returns SimpleHash with the converted EntityList plus
393    *        additional Data about the list.
394    * @exception StorageObjectException
395    */
396
397   public static SimpleHash makeSimpleHashWithEntitylistInfos(EntityList entList) throws StorageObjectException {
398     SimpleHash modelRoot = new SimpleHash();
399     if (entList!=null) {
400       modelRoot.put("contentlist", entList);
401       modelRoot.put("count", new SimpleScalar((new Integer(entList.getCount())).toString()));
402       if (entList.getWhere()!=null) {
403         modelRoot.put("where", new SimpleScalar(entList.getWhere()));
404         modelRoot.put("where_encoded", new SimpleScalar(URLEncoder.encode(entList.getWhere())));
405       }
406       if(entList.getOrder()!=null) {
407         modelRoot.put("order", new SimpleScalar(entList.getOrder()));
408         modelRoot.put("order_encoded", new SimpleScalar(URLEncoder.encode(entList.getOrder())));
409       }
410       modelRoot.put("from", new SimpleScalar((new Integer(entList.getFrom())).toString()));
411       modelRoot.put("to", new SimpleScalar((new Integer(entList.getTo())).toString()));
412
413       if (entList.hasNextBatch())
414         modelRoot.put("next", new SimpleScalar((new Integer(entList.getNextBatch())).toString()));
415       if (entList.hasPrevBatch())
416         modelRoot.put("prev", new SimpleScalar((new Integer(entList.getPrevBatch())).toString()));
417     }
418     return modelRoot;
419   }
420
421   /**
422    * Private methods to get template from a templateFilename
423    * @param templateFilename
424    * @return Template
425    * @exception HTMLParseException
426    */
427   private static Template getTemplateFor(String templateFilename) throws HTMLParseException
428   {
429     Template returnTemplate = null;
430     if (templateFilename!=null)
431       returnTemplate = (Template)templateCache.getItem(templateFilename,"template");
432
433
434     if (returnTemplate==null) {
435       theLog.printError("CACHE (ERR): Unknown template: " + templateFilename);
436       throw new HTMLParseException("Templatefile: "+ templateFilename + " not found.");
437     }
438
439     return returnTemplate;
440   }
441
442   public static void stopAutoUpdate(){
443     templateCache.stopAutoUpdate();
444     templateCache=null;
445   }
446
447 }