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