2 * Copyright (C) 2001, 2002 The Mir-coders group
\r
4 * This file is part of Mir.
\r
6 * Mir is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * Mir is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with Mir; if not, write to the Free Software
\r
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 * In addition, as a special exception, The Mir-coders gives permission to link
\r
21 * the code of this program with the com.oreilly.servlet library, any library
\r
22 * licensed under the Apache Software License, The Sun (tm) Java Advanced
\r
23 * Imaging library (JAI), The Sun JIMI library (or with modified versions of
\r
24 * the above that use the same license as the above), and distribute linked
\r
25 * combinations including the two. You must obey the GNU General Public
\r
26 * License in all respects for all of the code used other than the above
\r
27 * mentioned libraries. If you modify this file, you may extend this exception
\r
28 * to your version of the file, but you are not obligated to do so. If you do
\r
29 * not wish to do so, delete this exception statement from your version.
\r
34 import java.io.PrintWriter;
\r
35 import java.net.URLEncoder;
\r
36 import java.util.GregorianCalendar;
\r
37 import java.util.Iterator;
\r
38 import java.util.Locale;
\r
39 import java.util.Map;
\r
40 import java.util.Set;
\r
42 import javax.servlet.http.HttpServletResponse;
\r
44 import mir.config.MirPropertiesConfiguration;
\r
45 import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;
\r
46 import mir.entity.Entity;
\r
47 import mir.entity.EntityList;
\r
48 import mir.generator.FreemarkerGenerator;
\r
49 import mir.log.LoggerWrapper;
\r
50 import mir.storage.StorageObjectFailure;
\r
51 import mir.util.GeneratorHTMLFunctions;
\r
52 import mir.util.GeneratorIntegerFunctions;
\r
54 import org.apache.struts.util.MessageResources;
\r
56 import freemarker.template.FileTemplateCache;
\r
57 import freemarker.template.SimpleHash;
\r
58 import freemarker.template.SimpleList;
\r
59 import freemarker.template.SimpleScalar;
\r
60 import freemarker.template.Template;
\r
61 import freemarker.template.TemplateModelRoot;
\r
64 * Hilfsklasse zum Mergen von Template und Daten
\r
66 public final class HTMLTemplateProcessor {
\r
68 public static String templateDir;
\r
69 private static MirPropertiesConfiguration configuration;
\r
70 private static FileTemplateCache templateCache;
\r
71 private static String docRoot;
\r
72 private static String actionRoot;
\r
73 private static LoggerWrapper logger;
\r
76 // ML: configuration is not thread safe: it's risky to use it like this
\r
77 // actually I don't see why HTMLTemplateProcessor needs to be a
\r
78 // class with static methods. This causes more problems than it solves.
\r
80 configuration = MirPropertiesConfiguration.instance();
\r
82 catch (PropertiesConfigExc e) {
\r
83 e.printStackTrace();
\r
86 logger = new LoggerWrapper("TemplateEngine");
\r
89 configuration.getStringWithHome("Mir.TemplateDir");
\r
90 templateCache = new FileTemplateCache(templateDir);
\r
91 templateCache.setLoadingPolicy(FileTemplateCache.LOAD_ON_DEMAND);
\r
92 // gone in freemarker 1.7.1: templateCache.startAutoUpdate();
\r
95 docRoot = configuration.getString("RootUri");
\r
97 actionRoot = docRoot +configuration.getString("Producer.ActionServlet");
\r
99 catch (ConfigException ce) {
\r
100 // if Producer.ActionServlet is not set in the conf file
\r
101 actionRoot = docRoot + "/Mir";
\r
106 * empty private constructor, to avoid instantiation
\r
108 private HTMLTemplateProcessor() {
\r
111 // process-methods to merge different datastructures
\r
112 // with freemarker templates
\r
115 * Wandelt <code>anEntity</code> in freemarker-Struktur um, mischt die Daten mit
\r
116 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
\r
119 * @param templateFilename
\r
122 * @exception HTMLParseException
\r
125 public static void process(String templateFilename, Entity anEntity,
\r
126 PrintWriter out) throws HTMLParseException {
\r
127 if (anEntity == null)
\r
128 throw new HTMLParseException("entity is empty!");
\r
130 process(templateFilename, anEntity, out);
\r
134 * Wandelt Liste mit Entities <code>entList</code> in freemarker-Struktur um, mischt die Daten mit
\r
135 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
\r
138 * @param templateFilename
\r
141 * @exception HTMLParseException
\r
143 public static void process(HttpServletResponse res, String templateFilename,
\r
144 EntityList entList, PrintWriter out, Locale locale) throws HTMLParseException {
\r
145 process(res, templateFilename, entList, (String)null, (TemplateModelRoot)null,
\r
150 * Wandelt Entitylist in freemarker-Struktur um, f?gt <code>additionalModel</code>
\r
151 * unter dem Namen <code>additionalModelName</code> ein und mischt die Daten mit
\r
152 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
\r
155 * @param templateFilename
\r
157 * @param additionalModelName
\r
158 * @param additionalModel
\r
160 * @exception HTMLParseException
\r
163 public static void process(HttpServletResponse res, String templateFilename,
\r
164 EntityList entList, String additionalModelName,
\r
165 TemplateModelRoot additionalModel, PrintWriter out,
\r
166 Locale locale) throws HTMLParseException {
\r
168 SimpleHash modelRoot = new SimpleHash();
\r
170 if (entList == null) {
\r
171 process(null, templateFilename, modelRoot, out, locale);
\r
175 modelRoot = makeSimpleHashWithEntitylistInfos(entList);
\r
177 // Quickhack um mal ein Popup mit reinzunhemen ..
\r
178 if (additionalModelName != null && additionalModel != null)
\r
179 modelRoot.put(additionalModelName, additionalModel);
\r
181 process(res, templateFilename, modelRoot, out, locale);
\r
183 catch (StorageObjectFailure e) {
\r
184 throw new HTMLParseException(e.toString());
\r
191 * Gibt Template <code>templateFilename</code> an den PrintWriter
\r
194 * @param templateFilename
\r
197 * @exception HTMLParseException
\r
199 public static void process(String templateFilename, PrintWriter out,
\r
200 Locale locale) throws HTMLParseException {
\r
201 process(null, templateFilename, (TemplateModelRoot)null, out, locale);
\r
205 * Mischt die freemarker-Struktur <code>tmr</code> mit
\r
206 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
\r
209 * @param templateFilename
\r
212 * @exception HTMLParseException
\r
214 public static void process(HttpServletResponse res, String templateFilename,
\r
215 TemplateModelRoot tmr, PrintWriter out,
\r
216 Locale locale) throws HTMLParseException {
\r
217 process(res, templateFilename, tmr, null, out, locale);
\r
220 public static void process(HttpServletResponse res, String templateFilename,
\r
221 TemplateModelRoot tmr, TemplateModelRoot extra,
\r
222 PrintWriter out, Locale locale) throws HTMLParseException {
\r
223 process(res, templateFilename, tmr, extra, out, locale, "bundles.adminlocal", "bundles.admin");
\r
226 public static void process(HttpServletResponse res, String templateFilename,
\r
227 TemplateModelRoot tmr, TemplateModelRoot extra, PrintWriter out,
\r
228 Locale locale, String bundles) throws HTMLParseException {
\r
229 process(res, templateFilename, tmr, extra, out, locale, bundles, null);
\r
233 * Mischt die freemarker-Struktur <code>tmr</code> mit
\r
234 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
\r
237 * @param templateFilename
\r
240 * @exception HTMLParseException
\r
242 public static void process(HttpServletResponse res, String templateFilename,
\r
243 TemplateModelRoot tmr, TemplateModelRoot extra,
\r
244 PrintWriter out, Locale locale, String bundles,
\r
245 String bundles2) throws HTMLParseException {
\r
247 throw new HTMLParseException("no outputstream");
\r
248 Template tmpl = getTemplateFor(templateFilename);
\r
250 throw new HTMLParseException("no template: " + templateFilename);
\r
252 tmr = new SimpleHash();
\r
254 /** @todo what is this for? (rk) */
\r
255 String session = "";
\r
257 session = res.encodeURL("");
\r
260 SimpleHash configHash = new SimpleHash();
\r
262 // pass the whole config hash to the templates
\r
263 Iterator it = configuration.getKeys();
\r
265 while (it.hasNext()) {
\r
266 key = (String) it.next();
\r
267 configHash.put(key, new SimpleScalar(
\r
268 configuration.getString(key))
\r
272 // this does not come directly from the config file
\r
273 configHash.put("docRoot", new SimpleScalar(docRoot));
\r
274 configHash.put("actionRoot", new SimpleScalar(actionRoot + session));
\r
275 configHash.put("now",
\r
276 new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
\r
278 // this conform to updated freemarker syntax
\r
279 configHash.put("compressWhitespace",
\r
280 new freemarker.template.utility.CompressWhitespace());
\r
282 SimpleHash utilityHash = new SimpleHash();
\r
284 utilityHash.put("compressWhitespace",
\r
285 new freemarker.template.utility.CompressWhitespace());
\r
286 utilityHash.put("encodeURI",
\r
287 FreemarkerGenerator.makeAdapter(new GeneratorHTMLFunctions.
\r
288 encodeURIGeneratorFunction()));
\r
289 utilityHash.put("encodeHTML",
\r
290 FreemarkerGenerator.makeAdapter(new GeneratorHTMLFunctions.
\r
291 encodeHTMLGeneratorFunction()));
\r
292 utilityHash.put("isOdd",
\r
293 FreemarkerGenerator.makeAdapter(new GeneratorIntegerFunctions.
\r
295 utilityHash.put("increment",
\r
296 FreemarkerGenerator.makeAdapter(new GeneratorIntegerFunctions.
\r
297 incrementFunction()));
\r
299 catch (Throwable t) {
\r
300 throw new HTMLParseException(t.getMessage());
\r
303 SimpleHash outPutHash = new SimpleHash();
\r
305 if (extra != null) {
\r
306 outPutHash.put("extra", extra);
\r
308 outPutHash.put("data", tmr);
\r
309 outPutHash.put("config", configHash);
\r
310 outPutHash.put("utility", utilityHash);
\r
312 MessageResources messages = MessageResources.getMessageResources(bundles);
\r
313 if (bundles2!=null) {
\r
314 outPutHash.put("lang", new MessageMethodModel(locale, MessageResources.getMessageResources(bundles), MessageResources.getMessageResources(bundles2)));
\r
317 outPutHash.put("lang", new MessageMethodModel(locale, MessageResources.getMessageResources(bundles)));
\r
320 tmpl.process(outPutHash, out);
\r
324 * Converts Entity-List to SimpleList of SimpleHashes.
\r
325 * @param aList ist eine Liste von Entity
\r
326 * @return eine freemarker.template.SimpleList von SimpleHashes.
\r
328 * @deprecated EntityLists comply with TemplateListModel now.
\r
330 public static SimpleList makeSimpleList(EntityList aList) throws StorageObjectFailure {
\r
331 logger.warn("using deprecated makeSimpleList(entityList) - a waste of resources");
\r
332 SimpleList simpleList = new SimpleList();
\r
333 if (aList != null) {
\r
334 for (int i = 0; i < aList.size(); i++) {
\r
335 simpleList.add(aList.elementAt(i));
\r
342 * Konvertiert ein EntityList in ein freemarker.template.SimpleHash-Modell. Im Hash
\r
343 * sind die einzelnen Entities ueber ihre id zu erreichen.
\r
344 * @param aList ist die EntityList
\r
345 * @return SimpleHash mit den entsprechenden freemarker Daten
\r
348 public static SimpleHash makeSimpleHash(EntityList aList) throws
\r
349 StorageObjectFailure {
\r
350 SimpleHash simpleHash = new SimpleHash();
\r
351 Entity currentEntity;
\r
353 if (aList != null) {
\r
354 for (int i = 0; i < aList.size(); i++) {
\r
355 currentEntity = (Entity) aList.elementAt(i);
\r
356 simpleHash.put(currentEntity.getId(), currentEntity);
\r
363 * Konvertiert ein Hashtable mit den keys und values als String
\r
364 * in ein freemarker.template.SimpleHash-Modell
\r
365 * @param mergeData der Map mit den String / String Daten
\r
366 * @return SimpleHash mit den entsprechenden freemarker Daten
\r
369 public static SimpleHash makeSimpleHash(Map mergeData) {
\r
370 SimpleHash modelRoot = new SimpleHash();
\r
372 if (mergeData != null) {
\r
373 Set set = mergeData.keySet();
\r
374 Iterator it = set.iterator();
\r
375 for (int i = 0; i < set.size(); i++) {
\r
376 aField = (String) it.next();
\r
377 modelRoot.put(aField, (String) mergeData.get(aField));
\r
384 * Converts EntityList in SimpleHash and adds additional information
\r
385 * to the returned SimpleHash
\r
388 * @return SimpleHash returns SimpleHash with the converted EntityList plus
\r
389 * additional Data about the list.
\r
390 * @exception StorageObjectException
\r
393 public static SimpleHash makeSimpleHashWithEntitylistInfos(EntityList entList) throws
\r
394 StorageObjectFailure {
\r
395 SimpleHash modelRoot = new SimpleHash();
\r
396 if (entList != null) {
\r
397 modelRoot.put("contentlist", entList);
\r
398 modelRoot.put("count",
\r
399 new SimpleScalar( (new Integer(entList.getCount())).toString()));
\r
400 if (entList.getWhere() != null) {
\r
401 modelRoot.put("where", new SimpleScalar(entList.getWhere()));
\r
402 modelRoot.put("where_encoded",
\r
403 new SimpleScalar(URLEncoder.encode(entList.getWhere())));
\r
405 if (entList.getOrder() != null) {
\r
406 modelRoot.put("order", new SimpleScalar(entList.getOrder()));
\r
407 modelRoot.put("order_encoded",
\r
408 new SimpleScalar(URLEncoder.encode(entList.getOrder())));
\r
410 modelRoot.put("from",
\r
411 new SimpleScalar( (new Integer(entList.getFrom())).toString()));
\r
412 modelRoot.put("to",
\r
413 new SimpleScalar( (new Integer(entList.getTo())).toString()));
\r
415 if (entList.hasNextBatch())
\r
416 modelRoot.put("next",
\r
417 new SimpleScalar( (new Integer(entList.getNextBatch())).
\r
419 if (entList.hasPrevBatch())
\r
420 modelRoot.put("prev",
\r
421 new SimpleScalar( (new Integer(entList.getPrevBatch())).
\r
428 * Private methods to get template from a templateFilename
\r
429 * @param templateFilename
\r
431 * @exception HTMLParseException
\r
433 private static Template getTemplateFor(String templateFilename) throws
\r
434 HTMLParseException {
\r
435 Template returnTemplate = null;
\r
436 if (templateFilename != null)
\r
437 returnTemplate = (Template) templateCache.getItem(templateFilename,
\r
440 if (returnTemplate == null) {
\r
441 logger.error("CACHE (ERR): Unknown template: " + templateFilename);
\r
442 throw new HTMLParseException("Templatefile: " + templateFilename + " not found.");
\r
445 return returnTemplate;
\r
448 public static void stopAutoUpdate() {
\r
449 templateCache.stopAutoUpdate();
\r
450 templateCache = null;
\r