2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
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.
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.
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
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.
32 import java.io.PrintWriter;
33 import java.net.URLEncoder;
34 import java.util.GregorianCalendar;
35 import java.util.Iterator;
36 import java.util.Locale;
40 import javax.servlet.http.HttpServletResponse;
42 import mir.config.MirPropertiesConfiguration;
43 import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;
44 import mir.entity.Entity;
45 import mir.entity.EntityList;
46 import mir.generator.FreemarkerGenerator;
47 import mir.log.LoggerWrapper;
48 import mir.storage.StorageObjectFailure;
49 import mir.util.GeneratorHTMLFunctions;
50 import mir.util.GeneratorIntegerFunctions;
51 import mir.util.ResourceBundleGeneratorFunction;
53 import org.apache.struts.util.MessageResources;
55 import freemarker.template.FileTemplateCache;
56 import freemarker.template.SimpleHash;
57 import freemarker.template.SimpleList;
58 import freemarker.template.SimpleScalar;
59 import freemarker.template.Template;
60 import freemarker.template.TemplateModelRoot;
63 * Hilfsklasse zum Mergen von Template und Daten
65 public final class HTMLTemplateProcessor {
67 public static String templateDir;
68 private static final String[] bundles = { "bundles.adminlocal", "bundles.admin" };
69 private static MirPropertiesConfiguration configuration;
70 private static FileTemplateCache templateCache;
71 private static String docRoot;
72 private static String actionRoot;
73 private static LoggerWrapper logger;
76 // ML: configuration is not thread safe: it's risky to use it like this
77 // actually I don't see why HTMLTemplateProcessor needs to be a
78 // class with static methods. This causes more problems than it solves.
80 configuration = MirPropertiesConfiguration.instance();
82 catch (PropertiesConfigExc e) {
86 logger = new LoggerWrapper("TemplateEngine");
89 configuration.getStringWithHome("Mir.TemplateDir");
90 templateCache = new FileTemplateCache(templateDir);
91 templateCache.setLoadingPolicy(FileTemplateCache.LOAD_ON_DEMAND);
92 // gone in freemarker 1.7.1: templateCache.startAutoUpdate();
95 docRoot = configuration.getString("RootUri");
97 actionRoot = docRoot +configuration.getString("Producer.ActionServlet");
99 catch (ConfigException ce) {
100 // if Producer.ActionServlet is not set in the conf file
101 actionRoot = docRoot + "/Mir";
106 * empty private constructor, to avoid instantiation
108 private HTMLTemplateProcessor() {
112 * Wandelt Liste mit Entities <code>entList</code> in freemarker-Struktur um, mischt die Daten mit
113 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
116 * @param templateFilename
119 * @exception HTMLParseException
122 public static void process(HttpServletResponse res, String templateFilename, EntityList entList, PrintWriter out, Locale locale, Locale aFallbackLocale) throws HTMLParseException {
123 process(res, templateFilename, entList, (String)null, (TemplateModelRoot) null, out, locale, aFallbackLocale);
127 * Wandelt Entitylist in freemarker-Struktur um, f?gt <code>additionalModel</code>
128 * unter dem Namen <code>additionalModelName</code> ein und mischt die Daten mit
129 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
132 * @param templateFilename
134 * @param additionalModelName
135 * @param additionalModel
137 * @exception HTMLParseException
140 public static void process(HttpServletResponse res, String templateFilename,
141 EntityList entList, String additionalModelName,
142 TemplateModelRoot additionalModel, PrintWriter out,
143 Locale locale, Locale aFallbackLocale) throws HTMLParseException {
145 SimpleHash modelRoot = new SimpleHash();
147 if (entList == null) {
148 process(null, templateFilename, modelRoot, null, out, locale, aFallbackLocale);
152 modelRoot = makeSimpleHashWithEntitylistInfos(entList);
154 // Quickhack um mal ein Popup mit reinzunhemen ..
155 if (additionalModelName != null && additionalModel != null)
156 modelRoot.put(additionalModelName, additionalModel);
158 process(res, templateFilename, modelRoot, null, out, locale, aFallbackLocale);
160 catch (StorageObjectFailure e) {
161 throw new HTMLParseException(e.toString());
168 * Mischt die freemarker-Struktur <code>tmr</code> mit
169 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
172 * @param templateFilename
175 * @exception HTMLParseException
177 public static void process(HttpServletResponse res, String templateFilename,
178 TemplateModelRoot tmr, PrintWriter out,
179 Locale locale, Locale aFallbackLocale) throws HTMLParseException {
180 process(res, templateFilename, tmr, null, out, locale, aFallbackLocale);
184 * Mischt die freemarker-Struktur <code>tmr</code> mit
185 * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter
188 * @param templateFilename
191 * @exception HTMLParseException
193 public static void process(HttpServletResponse res, String templateFilename,
194 TemplateModelRoot tmr, TemplateModelRoot extra,
195 PrintWriter out, Locale locale, Locale aFallbackLocale) throws HTMLParseException {
198 throw new HTMLParseException("no outputstream");
199 Template tmpl = getTemplateFor(templateFilename);
201 throw new HTMLParseException("no template: " + templateFilename);
203 tmr = new SimpleHash();
205 /** @todo what is this for? (rk) */
206 SimpleHash configHash = new SimpleHash();
208 // pass the whole config hash to the templates
209 Iterator it = configuration.getKeys();
211 while (it.hasNext()) {
212 key = (String) it.next();
213 configHash.put(key, new SimpleScalar(
214 configuration.getString(key))
218 // this does not come directly from the config file
219 configHash.put("docRoot", new SimpleScalar(docRoot));
221 configHash.put("actionRoot", new SimpleScalar(res.encodeURL(actionRoot)));
222 configHash.put("now",
223 new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
225 // this conform to updated freemarker syntax
226 configHash.put("compressWhitespace",
227 new freemarker.template.utility.CompressWhitespace());
229 SimpleHash utilityHash = new SimpleHash();
231 utilityHash.put("compressWhitespace",
232 new freemarker.template.utility.CompressWhitespace());
233 utilityHash.put("encodeURI",
234 FreemarkerGenerator.makeAdapter(new GeneratorHTMLFunctions.
235 encodeURIGeneratorFunction()));
236 utilityHash.put("encodeHTML",
237 FreemarkerGenerator.makeAdapter(new GeneratorHTMLFunctions.
238 encodeHTMLGeneratorFunction()));
239 utilityHash.put("isOdd",
240 FreemarkerGenerator.makeAdapter(new GeneratorIntegerFunctions.
242 utilityHash.put("increment",
243 FreemarkerGenerator.makeAdapter(new GeneratorIntegerFunctions.
244 incrementFunction()));
246 catch (Throwable t) {
247 throw new HTMLParseException(t.getMessage());
250 SimpleHash outPutHash = new SimpleHash();
253 outPutHash.put("extra", extra);
255 outPutHash.put("data", tmr);
256 outPutHash.put("config", configHash);
257 outPutHash.put("utility", utilityHash);
259 MessageResources messages[] = new MessageResources[bundles.length];
261 for (int i=0; i<bundles.length; i++) {
262 messages[i] = MessageResources.getMessageResources(bundles[i]);
266 outPutHash.put("lang", FreemarkerGenerator.makeAdapter(new ResourceBundleGeneratorFunction(new Locale[] {locale, aFallbackLocale}, messages)));
268 catch (Throwable t) {
269 throw new HTMLParseException(t.toString());
272 tmpl.process(outPutHash, out);
276 * Converts Entity-List to SimpleList of SimpleHashes.
277 * @param aList ist eine Liste von Entity
278 * @return eine freemarker.template.SimpleList von SimpleHashes.
280 * @deprecated EntityLists comply with TemplateListModel now.
282 public static SimpleList makeSimpleList(EntityList aList) throws StorageObjectFailure {
283 logger.warn("using deprecated makeSimpleList(entityList) - a waste of resources");
284 SimpleList simpleList = new SimpleList();
286 for (int i = 0; i < aList.size(); i++) {
287 simpleList.add(aList.elementAt(i));
294 * Konvertiert ein EntityList in ein freemarker.template.SimpleHash-Modell. Im Hash
295 * sind die einzelnen Entities ueber ihre id zu erreichen.
296 * @param aList ist die EntityList
297 * @return SimpleHash mit den entsprechenden freemarker Daten
300 public static SimpleHash makeSimpleHash(EntityList aList) throws
301 StorageObjectFailure {
302 SimpleHash simpleHash = new SimpleHash();
303 Entity currentEntity;
306 for (int i = 0; i < aList.size(); i++) {
307 currentEntity = (Entity) aList.elementAt(i);
308 simpleHash.put(currentEntity.getId(), currentEntity);
315 * Konvertiert ein Hashtable mit den keys und values als String
316 * in ein freemarker.template.SimpleHash-Modell
317 * @param mergeData der Map mit den String / String Daten
318 * @return SimpleHash mit den entsprechenden freemarker Daten
321 public static SimpleHash makeSimpleHash(Map mergeData) {
322 SimpleHash modelRoot = new SimpleHash();
324 if (mergeData != null) {
325 Set set = mergeData.keySet();
326 Iterator it = set.iterator();
327 for (int i = 0; i < set.size(); i++) {
328 aField = (String) it.next();
329 modelRoot.put(aField, (String) mergeData.get(aField));
336 * Converts EntityList in SimpleHash and adds additional information
337 * to the returned SimpleHash
340 * @return SimpleHash returns SimpleHash with the converted EntityList plus
341 * additional Data about the list.
342 * @exception StorageObjectException
345 public static SimpleHash makeSimpleHashWithEntitylistInfos(EntityList entList) throws
346 StorageObjectFailure {
347 SimpleHash modelRoot = new SimpleHash();
348 if (entList != null) {
349 modelRoot.put("contentlist", entList);
350 modelRoot.put("count",
351 new SimpleScalar( (new Integer(entList.getCount())).toString()));
352 if (entList.getWhere() != null) {
353 modelRoot.put("where", new SimpleScalar(entList.getWhere()));
354 modelRoot.put("where_encoded",
355 new SimpleScalar(URLEncoder.encode(entList.getWhere())));
357 if (entList.getOrder() != null) {
358 modelRoot.put("order", new SimpleScalar(entList.getOrder()));
359 modelRoot.put("order_encoded",
360 new SimpleScalar(URLEncoder.encode(entList.getOrder())));
362 modelRoot.put("from",
363 new SimpleScalar( (new Integer(entList.getFrom())).toString()));
365 new SimpleScalar( (new Integer(entList.getTo())).toString()));
367 if (entList.hasNextBatch())
368 modelRoot.put("next",
369 new SimpleScalar( (new Integer(entList.getNextBatch())).
371 if (entList.hasPrevBatch())
372 modelRoot.put("prev",
373 new SimpleScalar( (new Integer(entList.getPrevBatch())).
380 * Private methods to get template from a templateFilename
381 * @param templateFilename
383 * @exception HTMLParseException
385 private static Template getTemplateFor(String templateFilename) throws
387 Template returnTemplate = null;
388 if (templateFilename != null)
389 returnTemplate = (Template) templateCache.getItem(templateFilename,
392 if (returnTemplate == null) {
393 logger.error("CACHE (ERR): Unknown template: " + templateFilename);
394 throw new HTMLParseException("Templatefile: " + templateFilename + " not found.");
397 return returnTemplate;