add no-cache Pragma and Cache-control headers to the http response.. I see no reason...
[mir.git] / source / Mir.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 the com.oreilly.servlet library, any library
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24  * the above that use the same license as the above), and distribute linked
25  * combinations including the two.  You must obey the GNU General Public
26  * License in all respects for all of the code used other than the above
27  * mentioned libraries.  If you modify this file, you may extend this exception
28  * to your version of the file, but you are not obligated to do so.  If you do
29  * not wish to do so, delete this exception statement from your version.
30  */
31
32 import freemarker.template.SimpleList;
33 import freemarker.template.SimpleHash;
34 import freemarker.template.SimpleScalar;
35 import mir.misc.HTMLParseException;
36 import mir.misc.HTMLTemplateProcessor;
37 import mir.misc.MirConfig;
38 import mir.misc.StringUtil;
39 import mir.servlet.*;
40 import mir.producer.*;
41
42 import mircoders.global.*;
43 import mircoders.localizer.*;
44 import mircoders.entity.EntityUsers;
45 import mircoders.module.ModuleMessage;
46 import mircoders.module.ModuleUsers;
47 import mircoders.storage.DatabaseArticleType;
48 import mircoders.storage.DatabaseMessages;
49 import mircoders.storage.DatabaseUsers;
50
51 import javax.servlet.ServletException;
52 import javax.servlet.UnavailableException;
53 import javax.servlet.http.HttpServletRequest;
54 import javax.servlet.http.HttpServletResponse;
55 import javax.servlet.http.HttpSession;
56 import java.io.IOException;
57 import java.io.PrintWriter;
58 import java.lang.reflect.Method;
59 import java.util.GregorianCalendar;
60 import java.util.HashMap;
61 import java.util.Locale;
62 import java.util.*;
63
64 import mir.log.Log;
65
66 /**
67  * Mir.java - main servlet, that dispatches to servletmodules
68  *
69  * @author $Author: mh $
70  * @version $Id: Mir.java,v 1.23 2002/12/06 08:12:42 mh Exp $
71  *
72  */
73
74
75 public class Mir extends AbstractServlet {
76
77     private static ModuleUsers usersModule = null;
78     private static ModuleMessage messageModule = null;
79     private final static HashMap servletModuleInstanceHash = new HashMap();
80
81     public HttpSession session;
82
83     public void doGet(HttpServletRequest req, HttpServletResponse res)
84             throws ServletException, IOException {
85         doPost(req, res);
86     }
87
88     public void doPost(HttpServletRequest req, HttpServletResponse res)
89             throws ServletException, IOException, UnavailableException {
90
91
92
93         long startTime = System.currentTimeMillis();
94         long sessionConnectTime = 0;
95         EntityUsers userEntity;
96         String http = "";
97
98         if (getServletContext().getAttribute("mir.confed") == null) {
99             getConfig(req);
100         }
101
102         MirConfig.setServletName(getServletName());
103
104         //*** test
105        // Log.info(this, "blalalala");
106
107         session = req.getSession(true);
108         userEntity = (EntityUsers) session.getAttribute("login.uid");
109
110         if (req.getServerPort() == 443) http = "https"; else http = "http";
111
112         //nothing in Mir can or should be cached as it's all dynamic...
113         //
114         //this needs to be done here and not per page (via meta tags) as some
115         //browsers have problems w/ it per-page -mh
116         res.setHeader("Pragma", "no-cache");
117         res.setDateHeader("Expires", 0);
118         res.setHeader("Cache-Control", "no-cache");
119         res.setContentType("text/html; charset="
120                             +MirConfig.getProp("Mir.DefaultEncoding"));
121         String moduleName = req.getParameter("module");
122
123         checkLanguage(session, req);
124
125         /** @todo for cleanup and readability this should be moved to
126          *  method loginIfNecessary() */
127
128         if (moduleName!=null && moduleName.equals("direct")) {
129           //...
130         }
131
132         // Authentifizierung
133         if ((moduleName != null && moduleName.equals("login")) || (userEntity==null)) {
134             String user = req.getParameter("login");
135             String passwd = req.getParameter("password");
136             theLog.printDebugInfo("--login: evaluating for user: " + user);
137             userEntity = allowedUser(user, passwd);
138             if (userEntity == null) {
139                 // login failed: redirecting to login
140                 theLog.printWarning("--login: failed!");
141                 _sendLoginPage(res, req, res.getWriter());
142                 return;
143             }
144             else if (moduleName!=null && moduleName.equals("login")) {
145                 // login successful
146
147                 theLog.printInfo("--login: successful! setting uid: " + userEntity.getId());
148                 session.setAttribute("login.uid", userEntity);
149                 theLog.printDebugInfo("--login: trying to retrieve login.target");
150                 String target = (String) session.getAttribute("login.target");
151
152                 if (target != null) {
153                     theLog.printDebugInfo("Redirect: " + target);
154                     int serverPort = req.getServerPort();
155                     String redirect = "";
156                     String redirectString = "";
157
158
159                     if (serverPort == 80) {
160                         redirect = res.encodeURL(http + "://" + req.getServerName() + target);
161                         redirectString = "<html><head><meta http-equiv=refresh content=\"1;URL="
162                                 + redirect
163                                 + "\"></head><body>going <a href=\"" + redirect + "\">Mir</a></body></html>";
164                     }
165                     else {
166                         redirect = res.encodeURL(http + "://" + req.getServerName() + ":" + req.getServerPort() + target);
167                         redirectString = "<html><head><meta http-equiv=refresh content=\"1;URL="
168                                 + redirect
169                                 + "\"></head><body>going <a href=\"" + redirect + "\">Mir</a></body></html>";
170                     }
171                     res.getWriter().println(redirectString);
172
173
174                     //res.sendRedirect(redirect);
175
176                 }
177                 else {
178                     // redirecting to default target
179                     theLog.printDebugInfo("--login: no target - redirecting to default");
180                     _sendStartPage(res, req, res.getWriter(), userEntity);
181                 }
182                 return;
183             } // if login succesful
184         } // if login
185
186         if (moduleName != null && moduleName.equals("logout")) {
187             theLog.printDebugInfo("--logout");
188             session.invalidate();
189
190             //session = req.getSession(true);
191             //checkLanguage(session, req);
192             _sendLoginPage(res, req, res.getWriter());
193             return;
194         }
195
196         // Check if authed!
197         if (userEntity == null) {
198             // redirect to loginpage
199             String redirectString = req.getRequestURI();
200             String queryString = req.getQueryString();
201             if (queryString != null && !queryString.equals("")) {
202                 redirectString += "?" + req.getQueryString();
203                 theLog.printDebugInfo("STORING: " + redirectString);
204                 session.setAttribute("login.target", redirectString);
205             }
206             _sendLoginPage(res, req, res.getWriter());
207             return;
208         }
209
210         // If no module is specified goto standard startpage
211         if (moduleName == null || moduleName.equals("")) {
212             theLog.printDebugInfo("no module: redirect to standardpage");
213             _sendStartPage(res, req, res.getWriter(), userEntity);
214             return;
215         }
216         // end of auth
217
218         // From now on regular dispatching...
219         try {
220             // get servletmodule by parameter and continue with dispacher
221             ServletModule smod = getServletModuleForName(moduleName);
222             ServletModuleDispatch.dispatch(smod, req, res);
223         }
224         catch (ServletModuleException e) {
225             handleError(req, res, res.getWriter(),
226                         "ServletException in Module " + moduleName + " -- " + e.getMessage());
227         }
228         catch (ServletModuleUserException e) {
229             handleUserError(req, res, res.getWriter(), e.getMessage());
230         }
231
232         // timing...
233         sessionConnectTime = System.currentTimeMillis() - startTime;
234         theLog.printInfo("EXECTIME (" + moduleName + "): " + sessionConnectTime + " ms");
235     }
236
237
238     /**
239      *  Private method getServletModuleForName returns ServletModule
240      *  from Cache
241      *
242      * @return ServletModule
243      *
244      */
245     private static ServletModule getServletModuleForName(String moduleName)
246             throws ServletModuleException {
247
248         // Instance in Map ?
249         if (!servletModuleInstanceHash.containsKey(moduleName)) {
250             // was not found in hash...
251             try {
252                 Class theServletModuleClass = null;
253                 try {
254                     // first we try to get ServletModule from stern.che3.servlet
255                     theServletModuleClass = Class.forName("mircoders.servlet.ServletModule" + moduleName);
256                 }
257                 catch (ClassNotFoundException e) {
258                     // on failure, we try to get it from lib-layer
259                     theServletModuleClass = Class.forName("mir.servlet.ServletModule" + moduleName);
260                 }
261                 Method m = theServletModuleClass.getMethod("getInstance", null);
262                 ServletModule smod = (ServletModule) m.invoke(null, null);
263                 // we put it into map for further reference
264                 servletModuleInstanceHash.put(moduleName, smod);
265                 return smod;
266             }
267             catch (Exception e) {
268                 throw new ServletModuleException("*** error resolving classname for " +
269                                                  moduleName + " -- " + e.getMessage());
270             }
271         }
272         else
273             return (ServletModule) servletModuleInstanceHash.get(moduleName);
274     }
275
276
277     private void handleError(HttpServletRequest req, HttpServletResponse res,
278                              PrintWriter out, String errorString) {
279
280         try {
281             theLog.printError(errorString);
282             SimpleHash modelRoot = new SimpleHash();
283             modelRoot.put("errorstring", new SimpleScalar(errorString));
284             modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
285             HTMLTemplateProcessor.process(res, MirConfig.getProp("Mir.ErrorTemplate"), modelRoot, out, getLocale(req));
286             out.close();
287         }
288         catch (Exception e) {
289           e.printStackTrace(System.out);
290           System.err.println("Error in ErrorTemplate: " + e.getMessage());
291         }
292     }
293
294     private void handleUserError(HttpServletRequest req, HttpServletResponse res,
295                                  PrintWriter out, String errorString) {
296         try {
297             theLog.printError(errorString);
298             SimpleHash modelRoot = new SimpleHash();
299             modelRoot.put("errorstring", new SimpleScalar(errorString));
300             modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
301             HTMLTemplateProcessor.process(res, MirConfig.getProp("Mir.UserErrorTemplate"),
302                                           modelRoot, out, getLocale(req));
303             out.close();
304         }
305         catch (Exception e) {
306             System.err.println("Error in UserErrorTemplate");
307         }
308
309     }
310
311     /**
312      *  evaluate login for user / password
313      */
314     protected EntityUsers allowedUser(String user, String password) {
315         try {
316             if (usersModule == null) usersModule = new ModuleUsers(DatabaseUsers.getInstance());
317             return usersModule.getUserForLogin(user, password);
318         }
319         catch (Exception e) {
320             theLog.printDebugInfo(e.getMessage());
321             e.printStackTrace();
322             return null;
323         }
324     }
325
326     // Redirect-methods
327     private void _sendLoginPage(HttpServletResponse res, HttpServletRequest req, PrintWriter out) {
328         String loginTemplate = MirConfig.getProp("Mir.LoginTemplate");//"login.template";
329         //  theLog.printDebugInfo("login template: "+loginTemplate);
330         String sessionUrl = res.encodeURL("");
331         //session = req.getSession(true);
332         try {
333             //theLog.printDebugInfo("login: "+lang);
334             //if(lang==null){
335             //  lang=getAcceptLanguage(req);
336             //}
337             SimpleHash mergeData = new SimpleHash();
338             mergeData.put("session", sessionUrl);
339             HTMLTemplateProcessor.process(res, loginTemplate, mergeData, out, getLocale(req));
340         }
341         catch (HTMLParseException e) {
342             handleError(req, res, out, "Error in logintemplate.");
343         }
344     }
345
346     private void _sendStartPage(HttpServletResponse res, HttpServletRequest req, PrintWriter out, EntityUsers userEntity) {
347         String startTemplate = "templates/admin/start_admin.template";
348         String sessionUrl = res.encodeURL("");
349         try {
350             // merge with logged in user and messages
351             SimpleHash mergeData = new SimpleHash();
352             mergeData.put("session", sessionUrl);
353             mergeData.put("login_user", userEntity);
354             if (messageModule == null) messageModule = new ModuleMessage(DatabaseMessages.getInstance());
355             mergeData.put("messages", messageModule.getByWhereClause(null, "webdb_create desc", 0, 10));
356
357             mergeData.put("articletypes", DatabaseArticleType.getInstance().selectByWhereClause("", "id", 0, 20));
358
359 /*
360             SimpleList producersData = new SimpleList();
361             Iterator i = MirGlobal.localizer().producers().factories().entrySet().iterator();
362             while (i.hasNext()) {
363               Map.Entry entry = (Map.Entry) i.next();
364
365               SimpleList producerVerbs = new SimpleList();
366               Iterator j = ((ProducerFactory) entry.getValue()).verbs();
367               while (j.hasNext()) {
368                 producerVerbs.add((String) j.next());
369               }
370
371               SimpleHash producerData = new SimpleHash();
372               producerData.put("key", (String) entry.getKey());
373               producerData.put("verbs", producerVerbs);
374
375               producersData.add(producerData);
376             }
377             mergeData.put("producers", producersData);
378  */
379
380
381             HTMLTemplateProcessor.process(res, startTemplate, mergeData, out, getLocale(req));
382         }
383         catch (Exception e) {
384             e.printStackTrace(System.out);
385             handleError(req, res, out, "error while trying to send startpage. " + e.getMessage());
386         }
387     }
388
389     public String getServletInfo() {
390         return "Mir "+MirConfig.getProp("Mir.Version");
391     }
392
393     private void checkLanguage(HttpSession session, HttpServletRequest req) {
394
395         // a lang parameter always sets the language
396         String lang = req.getParameter("lang");
397         if (lang != null) {
398             theLog.printInfo("selected language "+lang+" overrides accept-language");
399             setLanguage(session, lang);
400             setLocale(session, new Locale(lang, ""));
401         }
402         // otherwise store language from accept header in session
403         else if (session.getAttribute("Language") == null) {
404             theLog.printInfo("accept-language is "+req.getLocale().getLanguage());
405             setLanguage(session, req.getLocale().getLanguage());
406             setLocale(session, req.getLocale());
407         }
408     }
409 }
410