add the encodeHTML method
[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                 outPutHash.put("encodeHTML", new EncodeHTMLMethodModel() );
302
303                 tmpl.process(outPutHash,out);
304         }
305
306
307   /**
308    *   Converts Entity-List to SimpleList of SimpleHashes.
309    *   @param aList ist eine Liste von Entity
310    *   @return eine freemarker.template.SimpleList von SimpleHashes.
311    *
312    *    @deprecated EntityLists comply with TemplateListModel now.
313    */
314   public static SimpleList makeSimpleList(EntityList aList) throws StorageObjectException
315   {
316     theLog.printWarning("## using deprecated makeSimpleList(entityList) - a waste of resources");
317     SimpleList  simpleList = new SimpleList();
318     if (aList != null) {
319       for(int i=0;i<aList.size();i++) {
320         simpleList.add(aList.elementAt(i));
321       }
322     }
323     return simpleList;
324   }
325
326   /**
327    *  Konvertiert ein EntityList in ein freemarker.template.SimpleHash-Modell. Im Hash
328    *  sind die einzelnen Entities ueber ihre id zu erreichen.
329    *  @param aList ist die EntityList
330    *  @return SimpleHash mit den entsprechenden freemarker Daten
331    *
332    */
333   public static SimpleHash makeSimpleHash(EntityList aList) throws StorageObjectException
334   {
335     SimpleHash      simpleHash = new SimpleHash();
336     Entity          currentEntity;
337
338     if (aList != null) {
339       for (int i=0;i<aList.size();i++) {
340          currentEntity = (Entity)aList.elementAt(i);
341          simpleHash.put(currentEntity.getId(), currentEntity);
342       }
343     }
344     return simpleHash;
345   }
346
347   /**
348    *  Konvertiert ein Entity in ein freemarker.template.SimpleHash-Modell
349    *  @param entity ist die Entity
350    *  @return SimpleHash mit den entsprechenden freemarker Daten
351    *
352    *  @deprecated This method is deprecated and will be deleted in the next
353    *  release. Entity interfaces freemarker.template.TemplateHashModel now
354    *  and can be used in the same way as SimpleHash. It is not necessary any
355    *  more to make a SimpleHash from an Entity
356    */
357   public static SimpleHash makeSimpleHash(Entity entity) {
358     if (entity != null) {
359       theLog.printWarning("## using deprecated makeSimpleHash(entity) - a waste of resources");
360       return makeSimpleHash(entity.getValues());
361     }
362     else
363       return null;
364   }
365
366   /**
367    *  Konvertiert ein Hashtable mit den keys und values als String
368    *  in ein freemarker.template.SimpleHash-Modell
369    *  @param mergeData der HashMap mit den String / String Daten
370    *  @return SimpleHash mit den entsprechenden freemarker Daten
371    *
372    */
373   public static SimpleHash makeSimpleHash(HashMap mergeData)
374   {
375     SimpleHash modelRoot = new SimpleHash();
376     String aField;
377     if (mergeData != null) {
378       Set set = mergeData.keySet();
379       Iterator it =  set.iterator();
380       for (int i=0; i<set.size();i++)  {
381         aField = (String)it.next();
382         modelRoot.put(aField, (String)mergeData.get(aField));
383       }
384     }
385     return modelRoot;
386   }
387
388
389   /**
390    * Converts EntityList in SimpleHash and adds additional information
391    * to the returned SimpleHash
392    *
393    * @param entList
394    * @return SimpleHash returns SimpleHash with the converted EntityList plus
395    *        additional Data about the list.
396    * @exception StorageObjectException
397    */
398
399   public static SimpleHash makeSimpleHashWithEntitylistInfos(EntityList entList) throws StorageObjectException {
400     SimpleHash modelRoot = new SimpleHash();
401     if (entList!=null) {
402       modelRoot.put("contentlist", entList);
403       modelRoot.put("count", new SimpleScalar((new Integer(entList.getCount())).toString()));
404       if (entList.getWhere()!=null) {
405         modelRoot.put("where", new SimpleScalar(entList.getWhere()));
406         modelRoot.put("where_encoded", new SimpleScalar(URLEncoder.encode(entList.getWhere())));
407       }
408       if(entList.getOrder()!=null) {
409         modelRoot.put("order", new SimpleScalar(entList.getOrder()));
410         modelRoot.put("order_encoded", new SimpleScalar(URLEncoder.encode(entList.getOrder())));
411       }
412       modelRoot.put("from", new SimpleScalar((new Integer(entList.getFrom())).toString()));
413       modelRoot.put("to", new SimpleScalar((new Integer(entList.getTo())).toString()));
414
415       if (entList.hasNextBatch())
416         modelRoot.put("next", new SimpleScalar((new Integer(entList.getNextBatch())).toString()));
417       if (entList.hasPrevBatch())
418         modelRoot.put("prev", new SimpleScalar((new Integer(entList.getPrevBatch())).toString()));
419     }
420     return modelRoot;
421   }
422
423   /**
424    * Private methods to get template from a templateFilename
425    * @param templateFilename
426    * @return Template
427    * @exception HTMLParseException
428    */
429   private static Template getTemplateFor(String templateFilename) throws HTMLParseException
430   {
431     Template returnTemplate = null;
432     if (templateFilename!=null)
433       returnTemplate = (Template)templateCache.getItem(templateFilename,"template");
434
435
436     if (returnTemplate==null) {
437       theLog.printError("CACHE (ERR): Unknown template: " + templateFilename);
438       throw new HTMLParseException("Templatefile: "+ templateFilename + " not found.");
439     }
440
441     return returnTemplate;
442   }
443
444   public static void stopAutoUpdate(){
445     templateCache.stopAutoUpdate();
446     templateCache=null;
447   }
448
449 }