- major bugfix: many many threads were being created until a "can't create native...
[mir.git] / source / mircoders / localizer / basic / MirBasicPostingSessionHandler.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 mircoders.localizer.basic;
31
32 import java.util.Arrays;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Random;
38 import java.util.*;
39
40 import mir.config.MirPropertiesConfiguration;
41 import mir.entity.Entity;
42 import mir.log.LoggerWrapper;
43 import mir.session.Request;
44 import mir.session.Response;
45 import mir.session.Session;
46 import mir.session.SessionExc;
47 import mir.session.SessionFailure;
48 import mir.session.SessionHandler;
49 import mir.session.UploadedFile;
50 import mir.storage.StorageObject;
51 import mir.util.ExceptionFunctions;
52 import mircoders.entity.EntityComment;
53 import mircoders.global.MirGlobal;
54 import mircoders.media.MediaUploadProcessor;
55 import mircoders.module.ModuleComment;
56 import mircoders.storage.DatabaseComment;
57 import mircoders.storage.DatabaseCommentToMedia;
58 import mircoders.storage.DatabaseContent;
59 import mircoders.module.*;
60
61 /**
62  *
63  * <p>Title: Experimental session handler for comment postings </p>
64  * <p>Description: </p>
65  * <p>Copyright: Copyright (c) 2003</p>
66  * <p>Company: </p>
67  * @author not attributable
68  * @version 1.0
69  */
70
71 public abstract class MirBasicPostingSessionHandler implements SessionHandler {
72   protected LoggerWrapper logger;
73   protected MirPropertiesConfiguration configuration;
74
75   private String normalResponseGenerator;
76   private String dupeResponseGenerator;
77   private String unsupportedMediaTypeResponseGenerator;
78   private String finalResponseGenerator;
79
80
81   public MirBasicPostingSessionHandler() {
82     logger = new LoggerWrapper("Localizer.OpenPosting");
83     try {
84       configuration = MirPropertiesConfiguration.instance();
85     }
86     catch (Throwable t) {
87       logger.fatal("Cannot load configuration: " + t.toString());
88
89       throw new RuntimeException("Cannot load configuration: " + t.toString());
90     }
91   }
92
93   protected void setNormalResponseGenerator(String aGenerator) {
94     normalResponseGenerator = aGenerator;
95   }
96
97   protected void setResponseGenerators(String aNormalResponseGenerator, String aDupeResponseGenerator,
98         String anUnsupportedMediaTypeResponseGenerator, String aFinalResponseGenerator) {
99     setNormalResponseGenerator(aNormalResponseGenerator);
100     dupeResponseGenerator = aDupeResponseGenerator;
101     unsupportedMediaTypeResponseGenerator = anUnsupportedMediaTypeResponseGenerator;
102     finalResponseGenerator = aFinalResponseGenerator;
103   }
104
105   public void processRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
106     if (aSession.getAttribute("initialRequest")==null) {
107       initialRequest(aRequest, aSession, aResponse);
108       aSession.setAttribute("initialRequest", "no");
109     }
110     else {
111       subsequentRequest(aRequest, aSession, aResponse);
112     }
113   };
114
115   protected void initialRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
116     initializeSession(aRequest, aSession);
117     initializeResponseData(aRequest, aSession, aResponse);
118     makeInitialResponse(aRequest, aSession, aResponse);
119   }
120
121   public void subsequentRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
122     try {
123
124       try {
125         List validationErrors = new Vector();
126
127         if (!shouldProcessRequest(aRequest, aSession, validationErrors)) {
128           initializeResponseData(aRequest, aSession, aResponse);
129           makeResponse(aRequest, aSession, aResponse, validationErrors);
130         }
131         else {
132           preProcessRequest(aRequest, aSession);
133           Iterator i = aRequest.getUploadedFiles().iterator();
134           while (i.hasNext()) {
135             processUploadedFile(aRequest, aSession, (UploadedFile) i.next());
136           }
137           postProcessRequest(aRequest, aSession);
138           initializeResponseData(aRequest, aSession, aResponse);
139           makeFinalResponse(aRequest, aSession, aResponse);
140           aSession.terminate();
141         }
142       }
143       catch (Throwable t) {
144         initializeResponseData(aRequest, aSession, aResponse);
145         makeErrorResponse(aRequest, aSession, aResponse, t);
146         aSession.terminate();
147       }
148     }
149     catch (Throwable t) {
150       aSession.terminate();
151
152       throw new SessionFailure(t);
153     }
154   }
155
156   protected void initializeSession(Request aRequest, Session aSession) throws SessionExc, SessionFailure {
157     if (MirGlobal.abuse().getOpenPostingPassword()) {
158       String password = (String) aSession.getAttribute("password");
159       if (password==null) {
160         password = generateOnetimePassword();
161         aSession.setAttribute("password", password);
162       }
163     }
164     else {
165       aSession.deleteAttribute("password");
166     }
167
168     logger.debug("referrer = " + aRequest.getHeader("Referer"));
169
170     aSession.setAttribute("referer", aRequest.getHeader("Referer"));
171     aSession.setAttribute("nrmediaitems",
172         new Integer(configuration.getInt("ServletModule.OpenIndy.DefaultMediaUploadItems")));
173   }
174
175   protected void initializeResponseData(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
176     int nrMediaItems = ((Integer) aSession.getAttribute("nrmediaitems")).intValue();
177     List mediaItems = new Vector();
178     int i=0;
179
180     while (i<nrMediaItems) {
181       i++;
182       mediaItems.add(new Integer(i));
183     }
184
185     aResponse.setResponseValue("nrmediaitems", new Integer(nrMediaItems));
186     aResponse.setResponseValue("mediaitems", mediaItems);
187     aResponse.setResponseValue("password", aSession.getAttribute("password"));
188     aResponse.setResponseValue("referer", aSession.getAttribute("referer"));
189     aResponse.setResponseValue("errors", null);
190   }
191
192   protected void makeInitialResponse(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
193     aResponse.setResponseGenerator(normalResponseGenerator);
194   };
195
196   protected void makeResponse(Request aRequest, Session aSession, Response aResponse, List anErrors) throws SessionExc, SessionFailure {
197     aResponse.setResponseValue("errors", anErrors);
198     aResponse.setResponseGenerator(normalResponseGenerator);
199   };
200
201   protected void makeFinalResponse(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
202     aResponse.setResponseGenerator(finalResponseGenerator);
203   };
204
205   protected void makeErrorResponse(Request aRequest, Session aSession, Response aResponse, Throwable anError) throws SessionExc, SessionFailure {
206     anError.printStackTrace();
207     Throwable rootCause = ExceptionFunctions.traceCauseException(anError);
208
209     if (rootCause instanceof DuplicatePostingExc)
210       aResponse.setResponseGenerator(dupeResponseGenerator);
211     if (rootCause instanceof ModuleMediaType.UnsupportedMimeTypeExc) {
212       aResponse.setResponseValue("mimetype", ((ModuleMediaType.UnsupportedMimeTypeExc) rootCause).getMimeType());
213       aResponse.setResponseGenerator(unsupportedMediaTypeResponseGenerator);
214     }
215     else {
216       aResponse.setResponseValue("errorstring", anError.getMessage());
217       aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.ErrorTemplate"));
218     }
219   };
220
221   protected void preProcessRequest(Request aRequest, Session aSession) throws SessionExc, SessionFailure {
222   };
223   public void processUploadedFile(Request aRequest, Session aSession, UploadedFile aFile) throws SessionExc, SessionFailure {
224   };
225   protected void postProcessRequest(Request aRequest, Session aSession) throws SessionExc, SessionFailure {
226   };
227
228   protected boolean shouldProcessRequest(Request aRequest, Session aSession, List aValidationErrors) throws SessionExc, SessionFailure {
229     int nrMediaItems = ((Integer) aSession.getAttribute("nrmediaitems")).intValue();
230     try {
231       nrMediaItems = Math.min(configuration.getInt("ServletModule.OpenIndy.MaxMediaUploadItems"), Integer.parseInt(aRequest.getParameter("nrmediaitems")));
232     }
233     catch (Throwable t) {
234     }
235
236     aSession.setAttribute("nrmediaitems", new Integer(nrMediaItems));
237
238     if (aRequest.getParameter("post")==null)
239       return false;
240     else {
241       validate(aValidationErrors, aRequest, aSession);
242       return (aValidationErrors == null || aValidationErrors.size() == 0);
243     }
244   }
245
246   protected void validate(List aResults, Request aRequest, Session aSession) throws SessionExc, SessionFailure {
247   }
248
249   /**
250    * Class that represents a validation error
251    *
252    * <p>Title: </p>
253    * <p>Description: </p>
254    * <p>Copyright: Copyright (c) 2003</p>
255    * <p>Company: </p>
256    * @author not attributable
257    * @version 1.0
258    */
259
260   public class ValidationError {
261     private String field;
262     private String message;
263     private List parameters;
264
265     public ValidationError(String aField, String aMessage) {
266       this (aField, aMessage, new String[] {});
267     }
268
269     public ValidationError(String aField, String aMessage, Object aParameter) {
270       this (aField, aMessage, new Object[] {aParameter});
271     }
272
273     public ValidationError(String aField, String aMessage, Object[] aParameters) {
274       field = aField;
275       message = aMessage;
276       parameters = Arrays.asList(aParameters);
277     }
278
279     public String getMessage() {
280       return message;
281     }
282
283     public String getField() {
284       return field;
285     }
286
287     public List getParameters() {
288       return parameters;
289     }
290   }
291
292   /**
293    * Convenience validation method to test wether a field has been filled in
294    *
295    * @param aRequest
296    * @param aFieldName
297    * @param anErrorMessageResource
298    * @param aValidationResults
299    * @return
300    */
301
302   protected boolean testFieldEntered(Request aRequest, String aFieldName, String anErrorMessageResource, List aValidationResults) {
303     Object value = aRequest.getParameter(aFieldName);
304     if (value==null || !(value instanceof String) || ((String) value).trim().length()==0) {
305       aValidationResults.add(new ValidationError(aFieldName, anErrorMessageResource));
306       return false;
307     }
308     else
309       return true;
310   }
311
312   /**
313    * Convenience validation method to test wether a field is numeric
314
315    * @param aRequest
316    * @param aFieldName
317    * @param anErrorMessageResource
318    * @param aValidationResults
319    * @return
320    */
321
322   protected boolean testFieldIsNumeric(Request aRequest, String aFieldName, String anErrorMessageResource, List aValidationResults) {
323     Object value = aRequest.getParameter(aFieldName);
324     if (value!=null) {
325       try {
326         Integer.parseInt((String) value);
327         return true;
328       }
329       catch (Throwable t) {
330         aValidationResults.add(new ValidationError(aFieldName, anErrorMessageResource));
331         return false;
332       }
333     }
334     return true;
335   }
336
337   /**
338    * Convenience validation method to test wether a field is numeric
339
340    * @param aRequest
341    * @param aFieldName
342    * @param anErrorMessageResource
343    * @param aValidationResults
344    * @return
345    */
346
347   protected boolean testFieldLength(Request aRequest, String aFieldName, int aMaxLength, String anErrorMessageResource, List aValidationResults) {
348     String value = aRequest.getParameter(aFieldName);
349
350     if (value!=null) {
351       if (value.length()>aMaxLength) {
352         aValidationResults.add(new ValidationError(aFieldName, anErrorMessageResource));
353         return false;
354       }
355       else return true;
356     }
357     return true;
358   }
359
360   /**
361    * Method to generate a one-time password
362    *
363    * @return a password, to be used once
364    */
365
366   protected String generateOnetimePassword() {
367     Random r = new Random();
368     int random = r.nextInt();
369
370     long l = System.currentTimeMillis();
371
372     l = (l*l*l*l)/random;
373     if (l<0)
374       l = l * -1;
375
376     String returnString = ""+l;
377
378     return returnString.substring(5);
379   }
380
381
382   /**
383    *
384    * @param aRequest
385    * @param aStorage
386    * @return
387    * @throws SessionExc
388    * @throws SessionFailure
389    */
390
391   protected static final Map getIntersectingValues(Request aRequest, StorageObject aStorage) throws SessionExc, SessionFailure {
392     Map result = new HashMap();
393
394     Iterator i = aStorage.getFields().iterator();
395
396     while (i.hasNext()) {
397       String fieldName = (String) i.next();
398       Object value = aRequest.getParameter(fieldName);
399       if (value != null)
400         result.put(fieldName, value);
401     }
402
403     return result;
404   }
405
406   protected static class DuplicatePostingExc extends SessionExc {
407     public DuplicatePostingExc(String aMessage) {
408       super(aMessage);
409     }
410   }
411
412 }