fix bug where Mir.DefaultEncoding (the java one) was being sent out in the response...
[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 RK, mir-coders
61  * @version $Id: Mir.java,v 1.17.2.6 2002/12/10 21:13:58 mh Exp $
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         //make sure client browsers don't cache anything
104         setNoCaching(res);
105
106         res.setContentType("text/html; charset="
107                             +MirConfig.getProp("Mir.DefaultHTMLCharset"));
108         String moduleName = req.getParameter("module");
109
110         checkLanguage(session, req);
111
112         /** @todo for cleanup and readability this should be moved to
113          *  method loginIfNecessary() */
114
115         // Authentifizierung
116         if (moduleName != null && moduleName.equals("login")) {
117             String user = req.getParameter("login");
118             String passwd = req.getParameter("password");
119             theLog.printDebugInfo("--login: evaluating for user: " + user);
120             EntityUsers userEntity = allowedUser(user, passwd);
121             if (userEntity == null) {
122                 // login failed: redirecting to login
123                 theLog.printWarning("--login: failed!");
124                 _sendLoginPage(res, req, res.getWriter());
125                 return;
126             }
127             else {
128                 // login successful
129
130                 theLog.printInfo("--login: successful! setting uid: " + userEntity.getId());
131                 session.setAttribute("login.uid", userEntity);
132                 theLog.printDebugInfo("--login: trying to retrieve login.target");
133                 String target = (String) session.getAttribute("login.target");
134
135                 if (target != null) {
136                     theLog.printDebugInfo("Redirect: " + target);
137                     int serverPort = req.getServerPort();
138                     String redirect = "";
139                     String redirectString = "";
140
141
142                     if (serverPort == 80) {
143                         redirect = res.encodeURL(http + "://" + req.getServerName() + target);
144                         redirectString = "<html><head><meta http-equiv=refresh content=\"1;URL="
145                                 + redirect
146                                 + "\"></head><body>going <a href=\"" + redirect + "\">Mir</a></body></html>";
147                     }
148                     else {
149                         redirect = res.encodeURL(http + "://" + req.getServerName() + ":" + req.getServerPort() + target);
150                         redirectString = "<html><head><meta http-equiv=refresh content=\"1;URL="
151                                 + redirect
152                                 + "\"></head><body>going <a href=\"" + redirect + "\">Mir</a></body></html>";
153                     }
154                     res.getWriter().println(redirectString);
155
156
157                     //res.sendRedirect(redirect);
158
159                 }
160                 else {
161                     // redirecting to default target
162                     theLog.printDebugInfo("--login: no target - redirecting to default");
163                     _sendStartPage(res, req, res.getWriter(), userEntity);
164                 }
165                 return;
166             } // if login succesful
167         } // if login
168
169         if (moduleName != null && moduleName.equals("logout")) {
170             theLog.printDebugInfo("--logout");
171             session.invalidate();
172
173             //session = req.getSession(true);
174             //checkLanguage(session, req);
175             _sendLoginPage(res, req, res.getWriter());
176             return;
177         }
178
179         // Check if authed!
180         EntityUsers userEntity = (EntityUsers) session.getAttribute("login.uid");
181         if (userEntity == null) {
182             // redirect to loginpage
183             String redirectString = req.getRequestURI();
184             String queryString = req.getQueryString();
185             if (queryString != null && !queryString.equals("")) {
186                 redirectString += "?" + req.getQueryString();
187                 theLog.printDebugInfo("STORING: " + redirectString);
188                 session.setAttribute("login.target", redirectString);
189             }
190             _sendLoginPage(res, req, res.getWriter());
191             return;
192         }
193
194         // If no module is specified goto standard startpage
195         if (moduleName == null || moduleName.equals("")) {
196             theLog.printDebugInfo("no module: redirect to standardpage");
197             _sendStartPage(res, req, res.getWriter(), userEntity);
198             return;
199         }
200         // end of auth
201
202         // From now on regular dispatching...
203         try {
204             // get servletmodule by parameter and continue with dispacher
205             ServletModule smod = getServletModuleForName(moduleName);
206             ServletModuleDispatch.dispatch(smod, req, res);
207         }
208         catch (ServletModuleException e) {
209             handleError(req, res, res.getWriter(),
210                         "ServletException in Module " + moduleName + " -- " + e.toString());
211         }
212         catch (ServletModuleUserException e) {
213             handleUserError(req, res, res.getWriter(), e.getMsg());
214         }
215
216         // timing...
217         sessionConnectTime = System.currentTimeMillis() - startTime;
218         theLog.printInfo("EXECTIME (" + moduleName + "): " + sessionConnectTime + " ms");
219     }
220
221
222     /**
223      *  Private method getServletModuleForName returns ServletModule
224      *  from Cache
225      *
226      * @return ServletModule
227      *
228      */
229     private static ServletModule getServletModuleForName(String moduleName)
230             throws ServletModuleException {
231
232         // Instance in Map ?
233         if (!servletModuleInstanceHash.containsKey(moduleName)) {
234             // was not found in hash...
235             try {
236                 Class theServletModuleClass = null;
237                 try {
238                     // first we try to get ServletModule from stern.che3.servlet
239                     theServletModuleClass = Class.forName("mircoders.servlet.ServletModule" + moduleName);
240                 }
241                 catch (ClassNotFoundException e) {
242                     // on failure, we try to get it from lib-layer
243                     theServletModuleClass = Class.forName("mir.servlet.ServletModule" + moduleName);
244                 }
245                 Method m = theServletModuleClass.getMethod("getInstance", null);
246                 ServletModule smod = (ServletModule) m.invoke(null, null);
247                 // we put it into map for further reference
248                 servletModuleInstanceHash.put(moduleName, smod);
249                 return smod;
250             }
251             catch (Exception e) {
252                 throw new ServletModuleException("*** error resolving classname for " +
253                                                  moduleName + " -- " + e.toString());
254             }
255         }
256         else
257             return (ServletModule) servletModuleInstanceHash.get(moduleName);
258     }
259
260
261     private void handleError(HttpServletRequest req, HttpServletResponse res,
262                              PrintWriter out, String errorString) {
263
264         try {
265             theLog.printError(errorString);
266             SimpleHash modelRoot = new SimpleHash();
267             modelRoot.put("errorstring", new SimpleScalar(errorString));
268             modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
269             HTMLTemplateProcessor.process(res, MirConfig.getProp("Mir.ErrorTemplate"), modelRoot, out, getLocale(req));
270             out.close();
271         }
272         catch (Exception e) {
273             System.err.println("Error in ErrorTemplate");
274         }
275     }
276
277     private void handleUserError(HttpServletRequest req, HttpServletResponse res,
278                                  PrintWriter out, String errorString) {
279         try {
280             theLog.printError(errorString);
281             SimpleHash modelRoot = new SimpleHash();
282             modelRoot.put("errorstring", new SimpleScalar(errorString));
283             modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
284             HTMLTemplateProcessor.process(res, MirConfig.getProp("Mir.UserErrorTemplate"),
285                                           modelRoot, out, getLocale(req));
286             out.close();
287         }
288         catch (Exception e) {
289             System.err.println("Fehler in UserErrorTemplate");
290         }
291
292     }
293
294     /**
295      *  evaluate login for user / password
296      */
297     protected EntityUsers allowedUser(String user, String password) {
298         try {
299             if (usersModule == null) usersModule = new ModuleUsers(DatabaseUsers.getInstance());
300             return usersModule.getUserForLogin(user, password);
301         }
302         catch (Exception e) {
303             theLog.printDebugInfo(e.toString());
304             e.printStackTrace();
305             return null;
306         }
307     }
308
309     // Redirect-methods
310     private void _sendLoginPage(HttpServletResponse res, HttpServletRequest req, PrintWriter out) {
311         String loginTemplate = MirConfig.getProp("Mir.LoginTemplate");//"login.template";
312         //  theLog.printDebugInfo("login template: "+loginTemplate);
313         String sessionUrl = res.encodeURL("");
314         //session = req.getSession(true);
315         try {
316             //theLog.printDebugInfo("login: "+lang);
317             //if(lang==null){
318             //  lang=getAcceptLanguage(req);
319             //}
320             SimpleHash mergeData = new SimpleHash();
321             mergeData.put("session", sessionUrl);
322             HTMLTemplateProcessor.process(res, loginTemplate, mergeData, out, getLocale(req));
323         }
324         catch (HTMLParseException e) {
325             handleError(req, res, out, "Error in logintemplate.");
326         }
327     }
328
329     private void _sendStartPage(HttpServletResponse res, HttpServletRequest req, PrintWriter out, EntityUsers userEntity) {
330         String startTemplate = "admin/start_admin.template";
331         String sessionUrl = res.encodeURL("");
332         try {
333             // merge with logged in user and messages
334             SimpleHash mergeData = new SimpleHash();
335             mergeData.put("session", sessionUrl);
336             mergeData.put("login_user", userEntity);
337             if (messageModule == null) messageModule = new ModuleMessage(DatabaseMessages.getInstance());
338             mergeData.put("messages", messageModule.getByWhereClause(null, "webdb_create desc", 0, 10));
339             HTMLTemplateProcessor.process(res, startTemplate, mergeData, out, getLocale(req));
340         }
341         catch (Exception e) {
342             handleError(req, res, out, "error while trying to send startpage. " + e.toString());
343         }
344     }
345
346     public String getServletInfo() {
347         return "Mir "+MirConfig.getProp("Mir.Version");
348     }
349
350     private void checkLanguage(HttpSession session, HttpServletRequest req) {
351
352         // a lang parameter always sets the language
353         String lang = req.getParameter("lang");
354         if (lang != null) {
355             theLog.printInfo("selected language "+lang+" overrides accept-language");
356             setLanguage(session, lang);
357             setLocale(session, new Locale(lang, ""));
358         }
359         // otherwise store language from accept header in session
360         else if (session.getAttribute("Language") == null) {
361             theLog.printInfo("accept-language is "+req.getLocale().getLanguage());
362             setLanguage(session, req.getLocale().getLanguage());
363             setLocale(session, req.getLocale());
364         }
365     }
366 }
367