84e87bc2ded7af01354b9f38dad483d5c5b3c5b8
[mir.git] / source / mir / servlet / ServletModule.java
1 package mir.servlet;
2
3 import freemarker.template.SimpleHash;
4 import freemarker.template.TemplateModelRoot;
5 import mir.entity.EntityList;
6 import mir.misc.*;
7 import mir.module.AbstractModule;
8 import mir.module.ModuleException;
9 import mir.storage.StorageObject;
10 import mir.storage.StorageObjectException;
11
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 import javax.servlet.http.HttpSession;
15 import java.io.IOException;
16 import java.io.PrintWriter;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.Locale;
20
21
22 /**
23  * Abstract class ServletModule provides the base functionality for servlets.
24  * Deriving a class from ServletModule enables class to insert/edit/update/delete
25  * and list Entity from a Database via mainModule.
26  *
27  *
28  *  Abstrakte Klasse ServletModule stellt die Basisfunktionalitaet der
29  *  abgeleiteten ServletModule zur Verfügung.
30  *
31  * @version 28.6.1999
32  * @author RK
33  */
34
35 public abstract class ServletModule {
36
37     public String defaultAction;
38     protected Logfile theLog;
39     protected AbstractModule mainModule;
40     protected String templateListString;
41     protected String templateObjektString;
42     protected String templateConfirmString;
43
44     /**
45      * Singelton - Methode muss in den abgeleiteten Klassen ueberschrieben werden.
46      * @return ServletModule
47      */
48     public static ServletModule getInstance() {
49         return null;
50     }
51
52     /**
53      * get the session binded language
54      */
55     public String getLanguage(HttpServletRequest req) {
56         HttpSession session = req.getSession(false);
57         String language = (String) session.getAttribute("Language");
58         if (language == null) {
59             language = MirConfig.getProp("StandardLanguage");
60         }
61         return language;
62     }
63
64     /**
65      * get the locale either from the session or the accept-language header ot the request
66      * this supersedes getLanguage for the new i18n
67      */
68     public Locale getLocale(HttpServletRequest req) {
69         Locale loc = null;
70         HttpSession session = req.getSession(false);
71         if (session != null) {
72             // session can be null in case of logout
73             loc = (Locale) session.getAttribute("Locale");
74         }
75         // if there is nothing in the session get it fron the accept-language
76         if (loc == null) {
77             loc = req.getLocale();
78         }
79         return loc;
80     }
81
82     // ACHTUNG DEPRECATED::::
83     public void process(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException {
84     }
85
86
87     /**
88      *  list(req,res) - generische Listmethode. Wennn die Funktionalitaet
89      *  nicht reicht, muss sie in der abgeleiteten ServletModule-Klasse
90      *  ueberschreiben werden.
91      *
92      * @param req Http-Request, das vom Dispatcher durchgereicht wird
93      * @param res Http-Response, die vom Dispatcher durchgereicht wird
94      */
95     public void list(HttpServletRequest req, HttpServletResponse res)
96             throws ServletModuleException {
97         try {
98             EntityList theList;
99             String offsetParam = req.getParameter("offset");
100             int offset = 0;
101             PrintWriter out = res.getWriter();
102
103             // hier offsetcode bearbeiten
104             if (offsetParam != null && !offsetParam.equals("")) {
105                 offset = Integer.parseInt(offsetParam);
106             }
107             if (req.getParameter("next") != null) {
108                 offset = Integer.parseInt(req.getParameter("nextoffset"));
109             }
110             else {
111                 if (req.getParameter("prev") != null) {
112                     offset = Integer.parseInt(req.getParameter("prevoffset"));
113                 }
114             }
115             theList = mainModule.getByWhereClause(null, offset);
116             //theList = mainModule.getByWhereClause((String)null, offset);
117             if (theList == null || theList.getCount() == 0 || theList.getCount() > 1) {
118                 HTMLTemplateProcessor.process(res, templateListString, theList, out, getLocale(req));
119             }
120             else {
121                 deliver(req, res, theList.elementAt(0), templateObjektString);
122             }
123         }
124         catch (Exception e) {
125             throw new ServletModuleException(e.toString());
126         }
127     }
128
129     /**
130      *  add(req,res) - generische Addmethode. Wennn die Funktionalitaet
131      *  nicht reicht, muss sie in der abgeleiteten ServletModule-Klasse
132      *  ueberschreiben werden.
133      * @param req Http-Request, das vom Dispatcher durchgereicht wird
134      * @param res Http-Response, die vom Dispatcher durchgereicht wird
135      */
136     public void add(HttpServletRequest req, HttpServletResponse res)
137             throws ServletModuleException {
138
139         try {
140             SimpleHash mergeData = new SimpleHash();
141             mergeData.put("new", "1");
142             deliver(req, res, mergeData, templateObjektString);
143         }
144         catch (Exception e) {
145             throw new ServletModuleException(e.toString());
146         }
147     }
148
149     /**
150      *  insert(req,res) - generische Insertmethode, folgt auf add.
151      *  Wennn die Funktionalitaet
152      *  nicht reicht, muss sie in der abgeleiteten ServletModule-Klasse
153      *  ueberschreiben werden.
154      *
155      * @param req Http-Request, das vom Dispatcher durchgereicht wird
156      * @param res Http-Response, die vom Dispatcher durchgereicht wird
157      */
158     public void insert(HttpServletRequest req, HttpServletResponse res)
159             throws ServletModuleException, ServletModuleUserException {
160         try {
161             HashMap withValues = getIntersectingValues(req, mainModule.getStorageObject());
162             theLog.printDebugInfo("--trying to add...");
163             String id = mainModule.add(withValues);
164             theLog.printDebugInfo("--trying to deliver..." + id);
165             list(req, res);
166         }
167         catch (Exception e) {
168             throw new ServletModuleException(e.toString());
169         }
170     }
171
172     /**
173      *  delete(req,res) - generische Deletemethode. Wennn die Funktionalitaet
174      *  nicht reicht, muss sie in der abgeleiteten ServletModule-Klasse
175      *  ueberschreiben werden.
176      *
177      * @param req Http-Request, das vom Dispatcher durchgereicht wird
178      * @param res Http-Response, die vom Dispatcher durchgereicht wird
179      */
180
181     public void delete(HttpServletRequest req, HttpServletResponse res)
182             throws ServletModuleException {
183         try {
184             String idParam = req.getParameter("id");
185             if (idParam == null) throw new ServletModuleException("Falscher Aufruf: (id) nicht angegeben");
186             // Hier code zum Loeschen
187             String confirmParam = req.getParameter("confirm");
188             String cancelParam = req.getParameter("cancel");
189             if (confirmParam == null && cancelParam == null) {
190                 // HTML Ausgabe zum Confirmen!
191                 SimpleHash mergeData = new SimpleHash();
192                 String moduleClassName = mainModule.getClass().getName();
193                 int i = moduleClassName.indexOf(".Module");
194                 String moduleName = moduleClassName.substring(i + 7);
195                 mergeData.put("module", moduleName);
196                 mergeData.put("infoString", moduleName + ": " + idParam);
197                 mergeData.put("id", idParam);
198                 mergeData.put("where", req.getParameter("where"));
199                 mergeData.put("order", req.getParameter("order"));
200                 mergeData.put("offset", req.getParameter("offset"));
201                 deliver(req, res, mergeData, templateConfirmString);
202             }
203             else {
204                 if (confirmParam != null && !confirmParam.equals("")) {
205                     //theLog.printInfo("delete confirmed!");
206                     mainModule.deleteById(idParam);
207                     list(req, res); // back to list
208                 }
209                 else {
210                     if (req.getParameter("where") != null)
211                         list(req, res);
212                     else
213                         edit(req, res);
214                 }
215             }
216         }
217         catch (Exception e) {
218             throw new ServletModuleException(e.toString());
219         }
220     }
221
222     /**
223      *  edit(req,res) - generische Editmethode. Wennn die Funktionalitaet
224      *  nicht reicht, muss sie in der abgeleiteten ServletModule-Klasse
225      *  ueberschreiben werden.
226      *
227      * @param req Http-Request, das vom Dispatcher durchgereicht wird
228      * @param res Http-Response, die vom Dispatcher durchgereicht wird
229      */
230     public void edit(HttpServletRequest req, HttpServletResponse res)
231             throws ServletModuleException {
232         try {
233             String idParam = req.getParameter("id");
234             deliver(req, res, mainModule.getById(idParam), templateObjektString);
235         }
236         catch (ModuleException e) {
237             throw new ServletModuleException(e.toString());
238         }
239     }
240
241     /**
242      *  update(req,res) - generische Updatemethode. Wennn die Funktionalitaet
243      *  nicht reicht, muss sie in der abgeleiteten ServletModule-Klasse
244      *  ueberschreiben werden.
245      *
246      * @param req Http-Request, das vom Dispatcher durchgereicht wird
247      * @param res Http-Response, die vom Dispatcher durchgereicht wird
248      */
249
250     public void update(HttpServletRequest req, HttpServletResponse res)
251             throws ServletModuleException {
252         try {
253             String idParam = req.getParameter("id");
254             HashMap withValues = getIntersectingValues(req, mainModule.getStorageObject());
255             String id = mainModule.set(withValues);
256             //theLog.printInfo("Showing Entity with id: " + id);
257             //edit(req,res);
258             String whereParam = req.getParameter("where");
259             String orderParam = req.getParameter("order");
260             if ((whereParam != null && !whereParam.equals("")) || (orderParam != null && !orderParam.equals(""))) {
261                 //theLog.printDebugInfo("update to list");
262                 list(req, res);
263             }
264             else {
265                 edit(req, res);
266             }
267             //list(req,res);
268         }
269         catch (Exception e) {
270             throw new ServletModuleException(e.toString());
271         }
272     }
273
274     // Hilfsprozeduren
275     /**
276      public void predeliver(HttpServletResponse res, TemplateModelRoot rtm, String tmpl)
277      throws ServletModuleException {
278      try {
279      PrintWriter out = new LineFilterWriter(res.getWriter());
280      StringWriter a = new StringWriter();
281      deliver(new PrintWriter(a),rtm,tmpl);
282      out.write(a.toString());
283      out.flush();
284      } catch (Exception e) {
285      e.printStackTrace();System.err.println(e.toString());
286      }
287      }
288      */
289
290     /**
291      * deliver liefert das Template mit dem Filenamen templateFilename
292      * an den HttpServletResponse res aus, nachdem es mit den Daten aus
293      * TemplateModelRoot rtm gemischt wurde
294      *
295      * @param res Http-Response, die vom Dispatcher durchgereicht wird
296      * @param rtm beinahalten das freemarker.template.TempalteModelRoot mit den
297      *   Daten, die ins Template gemerged werden sollen.
298      * @param tmpl Name des Templates
299      * @exception ServletModuleException
300      */
301     public void deliver(HttpServletRequest req, HttpServletResponse res, TemplateModelRoot rtm, String templateFilename)
302             throws ServletModuleException {
303         if (rtm == null) rtm = new SimpleHash();
304         try {
305             //PrintWriter out =  new LineFilterWriter(res.getWriter());
306             PrintWriter out = res.getWriter();
307             HTMLTemplateProcessor.process(res, templateFilename, rtm, out, getLocale(req));
308             out.close();
309         }
310         catch (HTMLParseException e) {
311             throw new ServletModuleException(e.toString());
312         }
313         catch (IOException e) {
314             throw new ServletModuleException(e.toString());
315         }
316     }
317
318     /**
319      * deliver liefert das Template mit dem Filenamen templateFilename
320      * an den HttpServletResponse res aus, nachdem es mit den Daten aus
321      * TemplateModelRoot rtm gemischt wurde
322      *
323      * @param res Http-Response, die vom Dispatcher durchgereicht wird
324      * @param rtm beinahalten das freemarker.template.TempalteModelRoot mit den
325      *   Daten, die ins Template gemerged werden sollen.
326      * @param tmpl Name des Templates
327      * @exception ServletModuleException
328      */
329     public void deliver_compressed(HttpServletRequest req, HttpServletResponse res, TemplateModelRoot rtm, String templateFilename)
330             throws ServletModuleException {
331         if (rtm == null) rtm = new SimpleHash();
332         try {
333             PrintWriter out = new LineFilterWriter(res.getWriter());
334             //PrintWriter out =  res.getWriter();
335             HTMLTemplateProcessor.process(res, templateFilename, rtm, out, getLocale(req));
336             out.close();
337         }
338         catch (HTMLParseException e) {
339             throw new ServletModuleException(e.toString());
340         }
341         catch (IOException e) {
342             throw new ServletModuleException(e.toString());
343         }
344     }
345
346     /**
347      * deliver liefert das Template mit dem Filenamen templateFilename
348      * an den HttpServletResponse res aus, nachdem es mit den Daten aus
349      * TemplateModelRoot rtm gemischt wurde
350      *
351      * @param out ist der OutputStream, in den die gergten Daten geschickt werden sollen.
352      * @param rtm beinahalten das freemarker.template.TempalteModelRoot mit den
353      *   Daten, die ins Template gemerged werden sollen.
354      * @param tmpl Name des Templates
355      * @exception ServletModuleException
356      */
357     private void deliver(HttpServletResponse res, HttpServletRequest req, PrintWriter out, TemplateModelRoot rtm, String templateFilename)
358             throws HTMLParseException {
359         HTMLTemplateProcessor.process(res, templateFilename, rtm, out, getLocale(req));
360     }
361
362     /**
363      *  Wenn die abgeleitete Klasse diese Methode ueberschreibt und einen String mit einem
364      *  Methodennamen zurueckliefert, dann wird diese Methode bei fehlender Angabe des
365      *  doParameters ausgefuehrt.
366      *
367      * @return Name der Default-Action
368      */
369     public String defaultAction() {
370         return defaultAction;
371     }
372
373     /**
374      *  Hier kann vor der Datenaufbereitung schon mal ein response geschickt
375      *  werden (um das subjektive Antwortverhalten bei langsamen Verbindungen
376      *  zu verbessern).
377      */
378     public void predeliver(HttpServletRequest req, HttpServletResponse res) {
379         ;
380     }
381
382     /**
383      * Holt die Felder aus der Metadatenfelderliste des StorageObjects, die
384      * im HttpRequest vorkommen und liefert sie als HashMap zurueck
385      *
386      * @return HashMap mit den Werten
387      */
388     public HashMap getIntersectingValues(HttpServletRequest req, StorageObject theStorage)
389             throws ServletModuleException {
390         ArrayList theFieldList;
391         try {
392             theFieldList = theStorage.getFields();
393         }
394         catch (StorageObjectException e) {
395             throw new ServletModuleException("ServletModule.getIntersectingValues: " + e.toString());
396         }
397
398         HashMap withValues = new HashMap();
399         String aField, aValue;
400
401         for (int i = 0; i < theFieldList.size(); i++) {
402             aField = (String) theFieldList.get(i);
403             aValue = req.getParameter(aField);
404             if (aValue != null) withValues.put(aField, aValue);
405         }
406         return withValues;
407     }
408
409 }