1.1 restoration
[mir.git] / source / mir / servlet / ServletModule.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  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.
29  */
30 package mir.servlet;
31
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39 import javax.servlet.http.HttpSession;
40
41 import mir.config.MirPropertiesConfiguration;
42 import mir.entity.adapter.EntityAdapterEngine;
43 import mir.entity.adapter.EntityAdapterModel;
44 import mir.log.LoggerWrapper;
45 import mir.module.AbstractModule;
46 import mir.module.ModuleExc;
47 import mir.storage.StorageObject;
48 import mir.util.HTTPRequestParser;
49 import mir.util.URLBuilder;
50 import mircoders.global.MirGlobal;
51 import mircoders.servlet.ServletHelper;
52 import mircoders.localizer.MirLocalizerExc;
53 import multex.Failure;
54
55 /**
56  *
57  * <p>Title: </p>
58  * <p>Description: </p>
59  * <p>Copyright: Copyright (c) 2003</p>
60  * <p>Company: </p>
61  * @author not attributable
62  * @version 1.0
63  */
64
65 public abstract class ServletModule {
66   public String defaultAction;
67   protected LoggerWrapper logger;
68   protected static MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance();
69   private static Locale fallbackLocale = new Locale(configuration.getString("Mir.Admin.FallbackLanguage", "en"), "");
70
71   protected AbstractModule mainModule;
72   protected String definition;
73   protected EntityAdapterModel model;
74
75   protected String listGenerator;
76   protected String editGenerator;
77   protected String deleteConfirmationGenerator;
78   protected int nrEntitiesPerListPage;
79
80
81   public ServletModule(){
82     definition = null;
83     try {
84       model = MirGlobal.localizer().dataModel().adapterModel();
85     }
86     catch (MirLocalizerExc e) {
87       logger.error("Can't create model: " + e.toString());
88       throw new ServletModuleFailure("Can't retrieve model", e);
89     }
90
91
92
93     listGenerator = configuration.getString("ServletModule."+getOperationModuleName()+".ListTemplate");
94     editGenerator = configuration.getString("ServletModule."+getOperationModuleName()+".EditTemplate");
95     deleteConfirmationGenerator = configuration.getString("ServletModule."+getOperationModuleName()+".DeleteConfirmationTemplate");
96     nrEntitiesPerListPage =
97         configuration.getInt("ServletModule."+getOperationModuleName()+".ListSize",
98         configuration.getInt("ServletModule.Default.ListSize", 20));
99
100   }
101
102
103   public void logAdminUsage(HttpServletRequest aRequest, String anObject, String aDescription) {
104     MirGlobal.logAdminUsage(ServletHelper.getUser(aRequest), getOperationModuleName() + ":" + anObject, aDescription);
105   }
106
107   /**
108    * Singleton instance retrievel method. MUST be overridden in subclasses.
109    *
110    * @return ServletModule the single instance of the servletmodule class
111    */
112   public static ServletModule getInstance() {
113     return null;
114   }
115
116   /**
117    * Return the module name
118    */
119   protected String getOperationModuleName() {
120     return getClass().getName().substring((new String("mircoders.servlet.ServletModule")).length());
121   }
122
123   public static Locale[] getLocales(HttpServletRequest aRequest) {
124     return new Locale[] { getLocale(aRequest), fallbackLocale };
125   }
126
127   /**
128    * Return the locale either from the session or the accept-language header ot the request
129    * this supersedes getLanguage for the new i18n
130    */
131   public static Locale getLocale(HttpServletRequest aRequest) {
132     Locale loc = null;
133     HttpSession session = aRequest.getSession(false);
134     if (session != null) {
135       // session can be null in case of logout
136       loc = (Locale) session.getAttribute("locale");
137     }
138     // if there is nothing in the session get it fron the accept-language
139     if (loc == null) {
140       loc = aRequest.getLocale();
141     }
142     return loc;
143   }
144
145   /**
146    * get the locale either from the session or the accept-language header ot the request
147    * this supersedes getLanguage for the new i18n
148    */
149   public Locale getFallbackLocale(HttpServletRequest aRequest) {
150     return fallbackLocale;
151   }
152
153   /**
154    * Function to specify the default ordering for lists. May be overridden.
155    *
156    *
157    * @return
158    */
159   public String getDefaultListOrdering() {
160
161     if (mainModule!=null && mainModule.getStorageObject()!=null){
162       if (mainModule.getStorageObject().getFieldNames().contains("webdb_create"))
163         return "webdb_create desc";
164     }
165
166     return "id asc";
167   }
168
169   /**
170    * Generic list servlet method
171    */
172
173   public void list(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
174   {
175     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
176
177     String where = requestParser.getParameter("where");
178     String order = requestParser.getParameterWithDefault("order", getDefaultListOrdering());
179     int offset = requestParser.getIntegerWithDefault("offset", 0);
180
181     returnList(aRequest, aResponse, where, order, offset);
182   }
183
184
185   public void returnList(HttpServletRequest aRequest, HttpServletResponse aResponse,
186      String aWhereClause, String anOrderByClause, int anOffset) throws ServletModuleExc {
187
188     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
189     URLBuilder urlBuilder = new URLBuilder();
190     int count;
191
192     try {
193       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest));
194
195       List list =
196          EntityAdapterEngine.retrieveAdapterList(model, definition, aWhereClause, anOrderByClause, nrEntitiesPerListPage, anOffset);
197
198       responseData.put("nexturl", null);
199       responseData.put("prevurl", null);
200       responseData.put("module", getOperationModuleName());
201
202       count=mainModule.getSize(aWhereClause);
203
204       urlBuilder.setValue("module", getOperationModuleName());
205       urlBuilder.setValue("do", "list");
206       urlBuilder.setValue("where", aWhereClause);
207       urlBuilder.setValue("order", anOrderByClause);
208
209       urlBuilder.setValue("searchfield", requestParser.getParameter("searchfield"));
210       urlBuilder.setValue("searchtext", requestParser.getParameter("searchtext"));
211       urlBuilder.setValue("searchispublished", requestParser.getParameter("searchispublished"));
212       urlBuilder.setValue("searchstatus", requestParser.getParameter("searchstatus"));
213       urlBuilder.setValue("searchorder", requestParser.getParameter("searchorder"));
214
215       responseData.put("searchfield", requestParser.getParameter("searchfield"));
216       responseData.put("searchtext", requestParser.getParameter("searchtext"));
217       responseData.put("searchispublished", requestParser.getParameter("searchispublished"));
218       responseData.put("searchstatus", requestParser.getParameter("searchstatus"));
219       responseData.put("searchorder", requestParser.getParameter("searchorder"));
220
221       urlBuilder.setValue("offset", anOffset);
222       responseData.put("offset" , new Integer(anOffset).toString());
223       responseData.put("thisurl" , urlBuilder.getQuery());
224
225       if (count>anOffset+nrEntitiesPerListPage) {
226         urlBuilder.setValue("offset", anOffset + nrEntitiesPerListPage);
227         responseData.put("nexturl" , urlBuilder.getQuery());
228       }
229
230       if (anOffset>0) {
231         urlBuilder.setValue("offset", Math.max(anOffset - nrEntitiesPerListPage, 0));
232         responseData.put("prevurl" , urlBuilder.getQuery());
233       }
234
235       responseData.put("entities", list);
236       responseData.put("from" , Integer.toString(anOffset+1));
237       responseData.put("count", Integer.toString(count));
238       responseData.put("to", Integer.toString(Math.min(anOffset+nrEntitiesPerListPage, count)));
239
240       ServletHelper.generateResponse(aResponse.getWriter(), responseData, listGenerator);
241     }
242     catch (Throwable e) {
243       throw new ServletModuleFailure(e);
244     }
245   }
246
247   public void editObject(HttpServletRequest aRequest, HttpServletResponse aResponse, String anId) throws ServletModuleExc {
248     try {
249       editObject(aRequest, aResponse, model.makeEntityAdapter(definition, mainModule.getById(anId)), false, anId);
250     }
251     catch (Throwable t) {
252       throw new ServletModuleFailure(t);
253     }
254   }
255
256   public void editObject(HttpServletRequest aRequest, HttpServletResponse aResponse, Object anObject, boolean anIsNew, String anId) throws ServletModuleExc {
257     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
258     URLBuilder urlBuilder = new URLBuilder();
259
260     try {
261       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest));
262
263       responseData.put("module", getOperationModuleName());
264       responseData.put("entity", anObject);
265       responseData.put("new", new Boolean(anIsNew));
266
267
268       urlBuilder.setValue("module", getOperationModuleName());
269       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
270       if (anIsNew)
271         urlBuilder.setValue("do", "add");
272       else {
273         urlBuilder.setValue("id", anId);
274         urlBuilder.setValue("do", "edit");
275       }
276       responseData.put("returnurl", requestParser.getParameter("returnurl"));
277       responseData.put("thisurl", urlBuilder.getQuery());
278
279       ServletHelper.generateResponse(aResponse.getWriter(), responseData, editGenerator);
280     }
281     catch (Throwable e) {
282       throw new ServletModuleFailure(e);
283     }
284   }
285
286   /**
287    * Generic add servlet method
288    */
289   public void add(HttpServletRequest aRequest, HttpServletResponse aResponse)
290       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
291
292     Map object = new HashMap();
293
294     Iterator i = mainModule.getStorageObject().getFieldNames().iterator();
295
296     while (i.hasNext())
297       object.put(i.next(), "");
298
299     initializeNewObject(object, aRequest, aResponse);
300
301     editObject(aRequest, aResponse, object, true, null);
302   }
303
304   protected void initializeNewObject(Map aNewObject, HttpServletRequest aRequest, HttpServletResponse aResponse) {
305   }
306
307   /**
308    * Generic edit servlet method
309    */
310   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
311     edit(aRequest, aResponse, aRequest.getParameter("id"));
312   }
313
314   /**
315    */
316   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse, String anIdentifier)
317       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
318     try {
319       editObject(aRequest, aResponse, model.makeEntityAdapter(definition, mainModule.getById(anIdentifier)), false, anIdentifier);
320     }
321     catch (Throwable e) {
322       throw new ServletModuleFailure(e);
323     }
324   }
325
326   /**
327    * Generic update servlet method
328    */
329   public void update(HttpServletRequest aRequest, HttpServletResponse aResponse)
330       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
331     try {
332       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
333
334       String id = aRequest.getParameter("id");
335       Map withValues = getIntersectingValues(aRequest, mainModule.getStorageObject());
336       mainModule.set(withValues);
337
338       logAdminUsage(aRequest, id, "object modified");
339
340       String returnUrl = requestParser.getParameter("returnurl");
341
342       if (returnUrl!=null) {
343         ServletHelper.redirect(aResponse, returnUrl);
344       }
345       else {
346         edit(aRequest, aResponse, id);
347       }
348     }
349     catch (Throwable e) {
350       throw new ServletModuleFailure(e);
351     }
352   }
353
354   /**
355    * Generic insert servlet method
356    */
357   public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse)
358       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
359     try {
360       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
361
362       Map object = getIntersectingValues(aRequest, mainModule.getStorageObject());
363
364       String id = processInstertedObject(object, aRequest, aResponse);
365
366       logAdminUsage(aRequest, id, "object inserted");
367
368       String returnUrl = requestParser.getParameter("returnurl");
369
370       if (returnUrl!=null) {
371         ServletHelper.redirect(aResponse, returnUrl);
372       }
373       else {
374         edit(aRequest, aResponse, id);
375       }
376     }
377     catch (Throwable e) {
378       throw new ServletModuleFailure(e);
379     }
380   }
381
382   /**
383    *
384    */
385   public String processInstertedObject(Map anObject, HttpServletRequest aRequest, HttpServletResponse aResponse) {
386     try {
387       return mainModule.add(anObject);
388     }
389     catch (ModuleExc t) {
390       throw new ServletModuleFailure(t);
391     }
392   };
393
394   /**
395    * Generic delete confirmation servlet method
396    */
397   public void confirmdelete(HttpServletRequest aRequest, HttpServletResponse aResponse) {
398     try {
399       String idParam = aRequest.getParameter("id");
400       String confirmParam = aRequest.getParameter("confirm");
401
402       if (confirmParam != null && !confirmParam.equals("")) {
403         mainModule.deleteById(idParam);
404         logAdminUsage(aRequest, idParam, "object deleted");
405         ServletHelper.redirect(aResponse, aRequest.getParameter("okurl"));
406       }
407       else
408         ServletHelper.redirect(aResponse, aRequest.getParameter("cancelurl"));
409     }
410     catch (Throwable t) {
411       throw new ServletModuleFailure(t);
412     }
413   }
414
415   /**
416    * Generic delete servlet method
417    */
418   public void delete(HttpServletRequest aRequest, HttpServletResponse aResponse)
419       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure  {
420     try {
421       String idParam = aRequest.getParameter("id");
422
423       if (idParam == null)
424         throw new ServletModuleExc("Invalid call to delete: no id supplied");
425
426       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest));
427
428       responseData.put("module", getOperationModuleName());
429       responseData.put("id", idParam);
430       responseData.put("cancelurl", aRequest.getParameter("cancelurl"));
431       responseData.put("okurl", aRequest.getParameter("okurl"));
432
433       ServletHelper.generateResponse(aResponse.getWriter(), responseData, deleteConfirmationGenerator);
434     }
435     catch (Throwable e) {
436       throw new ServletModuleFailure(e);
437     }
438   }
439
440   /**
441    */
442   public String defaultAction() {
443     return defaultAction;
444   }
445
446   /**
447    * Gets the fields from a httprequest and matches them with the metadata from
448    * the storage object. Returns the keys that match, with their values.
449    *
450    * @return Map with the values
451    */
452   public Map getIntersectingValues(HttpServletRequest aRequest, StorageObject theStorage)
453       throws ServletModuleExc, ServletModuleFailure {
454
455     HTTPRequestParser parser;
456     List theFieldList;
457
458     parser = new HTTPRequestParser(aRequest);
459
460     theFieldList = theStorage.getFieldNames();
461
462     Map withValues = new HashMap();
463     String aField, aValue;
464
465     for (int i = 0; i < theFieldList.size(); i++) {
466       aField = (String) theFieldList.get(i);
467
468       aValue = parser.getParameter(aField);
469       if (aValue != null)
470         withValues.put(aField, aValue);
471     }
472     return withValues;
473   }
474 }