2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
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.
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.
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
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.
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.lang.reflect.Method;
35 import java.util.GregorianCalendar;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Locale;
41 import java.util.Vector;
43 import javax.servlet.ServletException;
44 import javax.servlet.UnavailableException;
45 import javax.servlet.http.HttpServletRequest;
46 import javax.servlet.http.HttpServletResponse;
47 import javax.servlet.http.HttpSession;
49 import mir.config.MirPropertiesConfiguration;
50 import mir.generator.FreemarkerGenerator;
51 import mir.log.LoggerWrapper;
52 import mir.misc.HTMLTemplateProcessor;
53 import mir.misc.StringUtil;
54 import mir.servlet.AbstractServlet;
55 import mir.servlet.ServletModule;
56 import mir.servlet.ServletModuleDispatch;
57 import mir.servlet.ServletModuleExc;
58 import mir.servlet.ServletModuleUserExc;
59 import mir.util.ExceptionFunctions;
60 import mir.util.StringRoutines;
61 import mircoders.entity.EntityUsers;
62 import mircoders.global.MirGlobal;
63 import mircoders.module.ModuleMessage;
64 import mircoders.module.ModuleUsers;
65 import mircoders.storage.DatabaseArticleType;
66 import mircoders.storage.DatabaseMessages;
67 import mircoders.storage.DatabaseUsers;
69 import org.apache.struts.util.MessageResources;
71 import freemarker.template.SimpleHash;
72 import freemarker.template.SimpleList;
73 import freemarker.template.SimpleScalar;
74 import freemarker.template.TemplateModel;
80 * Mir.java - main servlet, that dispatches to servletmodules
82 * @author $Author: idfx $
83 * @version $Id: Mir.java,v 1.38 2003/03/09 19:14:21 idfx Exp $
86 public class Mir extends AbstractServlet {
87 private static ModuleUsers usersModule = null;
88 private static ModuleMessage messageModule = null;
89 private final static Map servletModuleInstanceHash = new HashMap();
91 //I don't know about making this static cause it removes the
92 //possibility to change the config on the fly.. -mh
93 private static List loginLanguages = null;
94 public HttpSession session;
96 public void doGet(HttpServletRequest aRequest, HttpServletResponse aResponse)
97 throws ServletException, IOException {
98 doPost(aRequest, aResponse);
101 protected TemplateModel getLoginLanguages() throws ServletException {
102 synchronized (Mir.class) {
104 if (loginLanguages == null) {
105 MessageResources messageResources2 =
106 MessageResources.getMessageResources("bundles.admin");
107 MessageResources messageResources =
108 MessageResources.getMessageResources("bundles.adminlocal");
110 StringRoutines.splitString(MirGlobal.getConfigPropertyWithDefault(
111 "Mir.Login.Languages", "en"), ";");
113 loginLanguages = new Vector();
115 Iterator i = languages.iterator();
117 while (i.hasNext()) {
118 String code = (String) i.next();
119 Locale locale = new Locale(code, "");
120 String name = messageResources.getMessage(locale, "languagename");
123 name = messageResources2.getMessage(locale, "languagename");
130 Map record = new HashMap();
131 record.put("name", name);
132 record.put("code", code);
133 loginLanguages.add(record);
137 return FreemarkerGenerator.makeAdapter(loginLanguages);
139 catch (Throwable t) {
140 throw new ServletException(t.getMessage());
145 // FIXME: this should probalby go into AbstractServlet so it can be used in
146 // OpenMir as well -mh
147 protected String getDefaultLanguage(HttpServletRequest aRequest) {
148 String defaultlanguage =
149 MirGlobal.getConfigPropertyWithDefault("Mir.Login.DefaultLanguage", "");
151 if (defaultlanguage.length() == 0) {
152 Locale locale = aRequest.getLocale();
153 defaultlanguage = locale.getLanguage();
156 return defaultlanguage;
159 public void doPost(HttpServletRequest aRequest, HttpServletResponse aResponse)
160 throws ServletException, IOException, UnavailableException {
161 long startTime = System.currentTimeMillis();
162 long sessionConnectTime = 0;
163 EntityUsers userEntity;
166 if ((configuration.getString("RootUri") == null) ||
167 configuration.getString("RootUri").equals("")) {
168 configuration.setProperty("RootUri", aRequest.getContextPath());
171 configuration.addProperty("ServletName", getServletName());
174 // Log.info(this, "blalalala");
175 session = aRequest.getSession(true);
176 userEntity = (EntityUsers) session.getAttribute("login.uid");
178 if (aRequest.getServerPort() == 443) {
184 //make sure client browsers don't cache anything
185 setNoCaching(aResponse);
187 //FIXME: this seems kind of hackish and only here because we can have
188 // default other than the one that the browser is set to.
189 Locale locale = new Locale(getDefaultLanguage(aRequest), "");
190 MessageResources messageResources =
191 MessageResources.getMessageResources("bundles.admin");
192 String htmlcharset = messageResources.getMessage(locale, "htmlcharset");
194 aResponse.setContentType("text/html; charset=" + htmlcharset);
196 String moduleName = aRequest.getParameter("module");
197 checkLanguage(session, aRequest);
199 /** @todo for cleanup and readability this should be moved to
200 * method loginIfNecessary() */
201 if ((moduleName != null) && moduleName.equals("direct")) {
206 if (((moduleName != null) && moduleName.equals("login")) ||
207 (userEntity == null)) {
208 String user = aRequest.getParameter("login");
209 String passwd = aRequest.getParameter("password");
210 logger.debug("--login: evaluating for user: " + user);
211 userEntity = allowedUser(user, passwd);
213 if (userEntity == null) {
214 // login failed: redirecting to login
215 logger.warn("--login: failed!");
216 _sendLoginPage(aResponse, aRequest, aResponse.getWriter());
219 } else if ((moduleName != null) && moduleName.equals("login")) {
221 logger.info("--login: successful! setting uid: " + userEntity.getId());
222 session.setAttribute("login.uid", userEntity);
223 logger.debug("--login: trying to retrieve login.target");
225 String target = (String) session.getAttribute("login.target");
227 if (target != null) {
228 logger.debug("Redirect: " + target);
230 int serverPort = aRequest.getServerPort();
231 String redirect = "";
232 String redirectString = "";
234 if (serverPort == 80) {
236 aResponse.encodeURL(http + "://" + aRequest.getServerName() + target);
238 "<html><head><meta http-equiv=refresh content=\"1;URL=" +
239 redirect + "\"></head><body>going <a href=\"" + redirect +
240 "\">Mir</a></body></html>";
243 aResponse.encodeURL(http + "://" + aRequest.getServerName() + ":" +
244 aRequest.getServerPort() + target);
246 "<html><head><meta http-equiv=refresh content=\"1;URL=" +
247 redirect + "\"></head><body>going <a href=\"" + redirect +
248 "\">Mir</a></body></html>";
251 aResponse.getWriter().println(redirectString);
253 //aResponse.sendRedirect(redirect);
255 // redirecting to default target
256 logger.debug("--login: no target - redirecting to default");
257 _sendStartPage(aResponse, aRequest, aResponse.getWriter(), userEntity);
262 // if login succesful
266 if ((moduleName != null) && moduleName.equals("logout")) {
267 logger.info("--logout");
268 session.invalidate();
270 //session = aRequest.getSession(true);
271 //checkLanguage(session, aRequest);
272 _sendLoginPage(aResponse, aRequest, aResponse.getWriter());
278 if (userEntity == null) {
279 // redirect to loginpage
280 String redirectString = aRequest.getRequestURI();
281 String queryString = aRequest.getQueryString();
283 if ((queryString != null) && !queryString.equals("")) {
284 redirectString += ("?" + aRequest.getQueryString());
285 logger.debug("STORING: " + redirectString);
286 session.setAttribute("login.target", redirectString);
289 _sendLoginPage(aResponse, aRequest, aResponse.getWriter());
294 // If no module is specified goto standard startpage
295 if ((moduleName == null) || moduleName.equals("")) {
296 logger.debug("no module: redirect to standardpage");
297 _sendStartPage(aResponse, aRequest, aResponse.getWriter(), userEntity);
303 // From now on regular dispatching...
305 // get servletmodule by parameter and continue with dispacher
306 ServletModule smod = getServletModuleForName(moduleName);
307 ServletModuleDispatch.dispatch(smod, aRequest, aResponse);
309 catch (Throwable e) {
310 Throwable cause = ExceptionFunctions.traceCauseException(e);
312 if (cause instanceof ServletModuleUserExc)
313 handleUserError(aRequest, aResponse, aResponse.getWriter(), (ServletModuleUserExc) cause);
315 handleError(aRequest, aResponse, aResponse.getWriter(), cause);
320 sessionConnectTime = System.currentTimeMillis() - startTime;
321 logger.info("EXECTIME (" + moduleName + "): " + sessionConnectTime + " ms");
325 * Private method getServletModuleForName returns ServletModule
329 * @return ServletModule
332 private static ServletModule getServletModuleForName(String moduleName) throws ServletModuleExc {
334 if (!servletModuleInstanceHash.containsKey(moduleName)) {
335 // was not found in hash...
337 Class theServletModuleClass = null;
340 // first we try to get ServletModule from stern.che3.servlet
341 theServletModuleClass =
342 Class.forName("mircoders.servlet.ServletModule" + moduleName);
343 } catch (ClassNotFoundException e) {
344 // on failure, we try to get it from lib-layer
345 theServletModuleClass =
346 Class.forName("mir.servlet.ServletModule" + moduleName);
349 Method m = theServletModuleClass.getMethod("getInstance", null);
350 ServletModule smod = (ServletModule) m.invoke(null, null);
352 // we put it into map for further reference
353 servletModuleInstanceHash.put(moduleName, smod);
357 catch (Exception e) {
358 throw new ServletModuleExc("*** error resolving classname for " + moduleName + " -- " + e.getMessage());
362 return (ServletModule) servletModuleInstanceHash.get(moduleName);
366 private void handleUserError(HttpServletRequest aRequest, HttpServletResponse aResponse,
367 PrintWriter out, ServletModuleUserExc anException) {
369 logger.info("user error: " + anException.getMessage());
370 SimpleHash modelRoot = new SimpleHash();
371 MessageResources messages = MessageResources.getMessageResources("bundles.admin");
372 modelRoot.put("errorstring",
374 messages.getMessage(getLocale(aRequest), anException.getMessage(), anException.getParameters())
376 modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));
377 HTMLTemplateProcessor.process(
378 aResponse,MirPropertiesConfiguration.instance().getString("Mir.UserErrorTemplate"),
379 modelRoot, out, getLocale(aRequest));
382 catch (Exception e) {
383 logger.error("Error in UserErrorTemplate");
388 private void handleError(HttpServletRequest aRequest, HttpServletResponse aResponse,PrintWriter out, Throwable anException) {
391 logger.error("error: " + anException);
392 SimpleHash modelRoot = new SimpleHash();
393 modelRoot.put("errorstring", new SimpleScalar(anException.getMessage()));
394 modelRoot.put("date", new SimpleScalar(StringUtil.date2readableDateTime(
395 new GregorianCalendar())));
396 HTMLTemplateProcessor.process(aResponse,MirPropertiesConfiguration.instance().getString("Mir.ErrorTemplate"),
397 modelRoot,out, getLocale(aRequest));
400 catch (Exception e) {
401 logger.error("Error in ErrorTemplate");
406 * evaluate login for user / password
408 protected EntityUsers allowedUser(String user, String password) {
410 if (usersModule == null) {
411 usersModule = new ModuleUsers(DatabaseUsers.getInstance());
414 return usersModule.getUserForLogin(user, password);
416 catch (Exception e) {
417 logger.debug(e.getMessage());
418 e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
425 private void _sendLoginPage(HttpServletResponse aResponse, HttpServletRequest aRequest,
427 String loginTemplate = configuration.getString("Mir.LoginTemplate");
428 String sessionUrl = aResponse.encodeURL("");
431 SimpleHash mergeData = new SimpleHash();
432 SimpleList languages = new SimpleList();
434 mergeData.put("session", sessionUrl);
436 mergeData.put("defaultlanguage", getDefaultLanguage(aRequest));
437 mergeData.put("languages", getLoginLanguages());
439 HTMLTemplateProcessor.process(aResponse, loginTemplate, mergeData, out,
440 getLocale(aRequest));
442 catch (Throwable e) {
443 handleError(aRequest, aResponse, out, e);
447 private void _sendStartPage(HttpServletResponse aResponse, HttpServletRequest aRequest,
448 PrintWriter out, EntityUsers userEntity) {
449 String startTemplate = "templates/admin/start_admin.template";
450 String sessionUrl = aResponse.encodeURL("");
453 // merge with logged in user and messages
454 SimpleHash mergeData = new SimpleHash();
455 mergeData.put("session", sessionUrl);
456 mergeData.put("login_user", userEntity);
458 if (messageModule == null) {
459 messageModule = new ModuleMessage(DatabaseMessages.getInstance());
462 mergeData.put("messages",
463 messageModule.getByWhereClause(null, "webdb_create desc", 0, 10));
465 mergeData.put("articletypes",
466 DatabaseArticleType.getInstance().selectByWhereClause("", "id", 0, 20));
468 HTMLTemplateProcessor.process(aResponse, startTemplate, mergeData, out,
469 getLocale(aRequest));
471 catch (Exception e) {
472 e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
473 handleError(aRequest, aResponse, out, e);
477 public String getServletInfo() {
478 return "Mir " + configuration.getString("Mir.Version");
481 private void checkLanguage(HttpSession session, HttpServletRequest aRequest) {
482 // a lang parameter always sets the language
483 String lang = aRequest.getParameter("language");
486 logger.info("selected language " + lang + " overrides accept-language");
487 setLanguage(session, lang);
488 setLocale(session, new Locale(lang, ""));
490 // otherwise store language from accept header in session
491 else if (session.getAttribute("Language") == null) {
492 logger.info("accept-language is " + aRequest.getLocale().getLanguage());
493 setLanguage(session, aRequest.getLocale().getLanguage());
494 setLocale(session, aRequest.getLocale());