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