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