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.SimpleHash;
33 import freemarker.template.SimpleScalar;
34 import mir.misc.HTMLParseException;
35 import mir.misc.HTMLTemplateProcessor;
36 import mir.misc.MirConfig;
37 import mir.misc.StringUtil;
38 import mir.servlet.*;
39 import mircoders.entity.EntityUsers;
40 import mircoders.module.ModuleMessage;
41 import mircoders.module.ModuleUsers;
42 import mircoders.storage.DatabaseMessages;
43 import mircoders.storage.DatabaseUsers;
44
45 import javax.servlet.ServletException;
46 import javax.servlet.UnavailableException;
47 import javax.servlet.http.HttpServletRequest;
48 import javax.servlet.http.HttpServletResponse;
49 import javax.servlet.http.HttpSession;
50 import java.io.IOException;
51 import java.io.PrintWriter;
52 import java.lang.reflect.Method;
53 import java.util.GregorianCalendar;
54 import java.util.HashMap;
55 import java.util.Locale;
56
57 /**
58  * Mir.java - main servlet, that dispatches to servletmodules
59  *
60  * @author $Author: mh $
61  * @version $Revision: 1.17.2.3 $ $Date: 2002/12/06 07:14:45 $
62  *
63  */
64
65
66 public class Mir extends AbstractServlet {
67
68     private static ModuleUsers usersModule = null;
69     private static ModuleMessage messageModule = null;
70     private final static HashMap servletModuleInstanceHash = new HashMap();
71
72     private static boolean nameSet = false;
73
74     public HttpSession session;
75
76     public void doGet(HttpServletRequest req, HttpServletResponse res)
77             throws ServletException, IOException {
78         doPost(req, res);
79     }
80
81     public void doPost(HttpServletRequest req, HttpServletResponse res)
82             throws ServletException, IOException, UnavailableException {
83
84         long startTime = System.currentTimeMillis();
85         long sessionConnectTime = 0;
86         String http = "";
87
88         // get the configration - this could conflict if 2 mirs are in the
89         // VM maybe? to be checked. -mh
90         if (getServletContext().getAttribute("mir.confed") == null) {
91             getConfig(req);
92         }
93
94         if (!nameSet) {
95           MirConfig.setAdminServletName(getServletName());
96           nameSet = true;
97         }
98
99         session = req.getSession(true);
100
101         if (req.getServerPort() == 443) http = "https"; else http = "http";
102
103         //nothing in Mir can or should be cached as it's all dynamic...
104         //
105         //this needs to be done here and not per page (via meta tags) as some
106         //browsers have problems w/ it per-page -mh
107         res.setHeader("Pragma", "no-cache");
108         res.setDateHeader("Expires", 0);
109         res.setHeader("Cache-Control", "no-cache");
110         res.setContentType("text/html; charset="
111                             +MirConfig.getProp("Mir.DefaultEncoding"));
112         String moduleName = req.getParameter("module");
113
114         checkLanguage(session, req);
115
116         /** @todo for cleanup and readability this should be moved to
117          *  method loginIfNecessary() */
118
119         // Authentifizierung
120         if (moduleName != null && moduleName.equals("login")) {
121             String user = req.getParameter("login");
122             String passwd = req.getParameter("password");
123             theLog.printDebugInfo("--login: evaluating for user: " + user);
124             EntityUsers userEntity = allowedUser(user, passwd);
125             if (userEntity == null) {
126                 // login failed: redirecting to login
127                 theLog.printWarning("--login: failed!");
128                 _sendLoginPage(res, req, res.getWriter());
129                 return;
130             }
131             else {
132                 // login successful
133
134                 theLog.printInfo("--login: successful! setting uid: " + userEntity.getId());
135                 session.setAttribute("login.uid", userEntity);
136                 theLog.printDebugInfo("--login: trying to retrieve login.target");
137                 String target = (String) session.getAttribute("login.target");
138
139                 if (target != null) {
140                     theLog.printDebugInfo("Redirect: " + target);
141                     int serverPort = req.getServerPort();
142                     String redirect = "";
143                     String redirectString = "";
144
145
146                     if (serverPort == 80) {
147                         redirect = res.encodeURL(http + "://" + req.getServerName() + target);
148                         redirectString = "<html><head><meta http-equiv=refresh content=\"1;URL="
149                                 + redirect
150                                 + "\"></head><body>going <a href=\"" + redirect + "\">Mir</a></body></html>";
151                     }
152                     else {
153                         redirect = res.encodeURL(http + "://" + req.getServerName() + ":" + req.getServerPort() + target);
154                         redirectString = "<html><head><meta http-equiv=refresh content=\"1;URL="
155                                 + redirect
156                                 + "\"></head><body>going <a href=\"" + redirect + "\">Mir</a></body></html>";
157                     }
158                     res.getWriter().println(redirectString);
159
160
161                     //res.sendRedirect(redirect);
162
163                 }
164                 else {
165                     // redirecting to default target
166                     theLog.printDebugInfo("--login: no target - redirecting to default");
167                     _sendStartPage(res, req, res.getWriter(), userEntity);
168                 }
169                 return;
170             } // if login succesful
171         } // if login
172
173         if (moduleName != null && moduleName.equals("logout")) {
174             theLog.printDebugInfo("--logout");
175             session.invalidate();
176
177             //session = req.getSession(true);
178             //checkLanguage(session, req);
179             _sendLoginPage(res, req, res.getWriter());
180             return;
181         }
182
183         // Check if authed!
184         EntityUsers userEntity = (EntityUsers) session.getAttribute("login.uid");
185         if (userEntity == null) {
186             // redirect to loginpage
187             String redirectString = req.getRequestURI();
188             String queryString = req.getQueryString();
189             if (queryString != null && !queryString.equals("")) {
190                 redirectString += "?" + req.getQueryString();
191                 theLog.printDebugInfo("STORING: " + redirectString);
192                 session.setAttribute("login.target", redirectString);
193             }
194             _sendLoginPage(res, req, res.getWriter());
195             return;
196         }
197
198         // If no module is specified goto standard startpage
199         if (moduleName == null || moduleName.equals("")) {
200             theLog.printDebugInfo("no module: redirect to standardpage");
201             _sendStartPage(res, req, res.getWriter(), userEntity);
202             return;
203         }
204         // end of auth
205
206         // From now on regular dispatching...
207         try {
208             // get servletmodule by parameter and continue with dispacher
209             ServletModule smod = getServletModuleForName(moduleName);
210             ServletModuleDispatch.dispatch(smod, req, res);
211         }
212         catch (ServletModuleException e) {
213             handleError(req, res, res.getWriter(),
214                         "ServletException in Module " + moduleName + " -- " + e.toString());
215         }
216         catch (ServletModuleUserException e) {
217             handleUserError(req, res, res.getWriter(), e.getMsg());
218         }
219
220         // timing...
221         sessionConnectTime = System.currentTimeMillis() - startTime;
222         theLog.printInfo("EXECTIME (" + moduleName + "): " + sessionConnectTime + " ms");
223     }
224
225
226     /**
227      *  Private method getServletModuleForName returns ServletModule
228      *  from Cache
229      *
230      * @return ServletModule
231      *
232      */
233     private static ServletModule getServletModuleForName(String moduleName)
234             throws ServletModuleException {
235
236         // Instance in Map ?
237         if (!servletModuleInstanceHash.containsKey(moduleName)) {
238             // was not found in hash...
239             try {
240                 Class theServletModuleClass = null;
241                 try {
242                     // first we try to get ServletModule from stern.che3.servlet
243                     theServletModuleClass = Class.forName("mircoders.servlet.ServletModule" + moduleName);
244                 }
245                 catch (ClassNotFoundException e) {
246                     // on failure, we try to get it from lib-layer
247                     theServletModuleClass = Class.forName("mir.servlet.ServletModule" + moduleName);
248                 }
249                 Method m = theServletModuleClass.getMethod("getInstance", null);
250                 ServletModule smod = (ServletModule) m.invoke(null, null);
251                 // we put it into map for further reference
252                 servletModuleInstanceHash.put(moduleName, smod);
253                 return smod;
254             }
255             catch (Exception e) {
256                 throw new ServletModuleException("*** error resolving classname for " +
257                                                  moduleName + " -- " + e.toString());
258             }
259         }
260         else
261             return (ServletModule) servletModuleInstanceHash.get(moduleName);
262     }
263
264
265     private void handleError(HttpServletRequest req, HttpServletResponse res,
266                              PrintWriter out, String errorString) {
267
268         try {
269             theLog.printError(errorString);
270             SimpleHash modelRoot = new SimpleHash();
271             modelRoot.put("errorstring", new SimpleScalar(errorString));
272             modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
273             HTMLTemplateProcessor.process(res, MirConfig.getProp("Mir.ErrorTemplate"), modelRoot, out, getLocale(req));
274             out.close();
275         }
276         catch (Exception e) {
277             System.err.println("Error in ErrorTemplate");
278         }
279     }
280
281     private void handleUserError(HttpServletRequest req, HttpServletResponse res,
282                                  PrintWriter out, String errorString) {
283         try {
284             theLog.printError(errorString);
285             SimpleHash modelRoot = new SimpleHash();
286             modelRoot.put("errorstring", new SimpleScalar(errorString));
287             modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
288             HTMLTemplateProcessor.process(res, MirConfig.getProp("Mir.UserErrorTemplate"),
289                                           modelRoot, out, getLocale(req));
290             out.close();
291         }
292         catch (Exception e) {
293             System.err.println("Fehler in UserErrorTemplate");
294         }
295
296     }
297
298     /**
299      *  evaluate login for user / password
300      */
301     protected EntityUsers allowedUser(String user, String password) {
302         try {
303             if (usersModule == null) usersModule = new ModuleUsers(DatabaseUsers.getInstance());
304             return usersModule.getUserForLogin(user, password);
305         }
306         catch (Exception e) {
307             theLog.printDebugInfo(e.toString());
308             e.printStackTrace();
309             return null;
310         }
311     }
312
313     // Redirect-methods
314     private void _sendLoginPage(HttpServletResponse res, HttpServletRequest req, PrintWriter out) {
315         String loginTemplate = MirConfig.getProp("Mir.LoginTemplate");//"login.template";
316         //  theLog.printDebugInfo("login template: "+loginTemplate);
317         String sessionUrl = res.encodeURL("");
318         //session = req.getSession(true);
319         try {
320             //theLog.printDebugInfo("login: "+lang);
321             //if(lang==null){
322             //  lang=getAcceptLanguage(req);
323             //}
324             SimpleHash mergeData = new SimpleHash();
325             mergeData.put("session", sessionUrl);
326             HTMLTemplateProcessor.process(res, loginTemplate, mergeData, out, getLocale(req));
327         }
328         catch (HTMLParseException e) {
329             handleError(req, res, out, "Error in logintemplate.");
330         }
331     }
332
333     private void _sendStartPage(HttpServletResponse res, HttpServletRequest req, PrintWriter out, EntityUsers userEntity) {
334         String startTemplate = "admin/start_admin.template";
335         String sessionUrl = res.encodeURL("");
336         try {
337             // merge with logged in user and messages
338             SimpleHash mergeData = new SimpleHash();
339             mergeData.put("session", sessionUrl);
340             mergeData.put("login_user", userEntity);
341             if (messageModule == null) messageModule = new ModuleMessage(DatabaseMessages.getInstance());
342             mergeData.put("messages", messageModule.getByWhereClause(null, "webdb_create desc", 0, 10));
343             HTMLTemplateProcessor.process(res, startTemplate, mergeData, out, getLocale(req));
344         }
345         catch (Exception e) {
346             handleError(req, res, out, "error while trying to send startpage. " + e.toString());
347         }
348     }
349
350     public String getServletInfo() {
351         return "Mir "+MirConfig.getProp("Mir.Version");
352     }
353
354     private void checkLanguage(HttpSession session, HttpServletRequest req) {
355
356         // a lang parameter always sets the language
357         String lang = req.getParameter("lang");
358         if (lang != null) {
359             theLog.printInfo("selected language "+lang+" overrides accept-language");
360             setLanguage(session, lang);
361             setLocale(session, new Locale(lang, ""));
362         }
363         // otherwise store language from accept header in session
364         else if (session.getAttribute("Language") == null) {
365             theLog.printInfo("accept-language is "+req.getLocale().getLanguage());
366             setLanguage(session, req.getLocale().getLanguage());
367             setLocale(session, req.getLocale());
368         }
369     }
370 }
371