test 123
[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  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30
31 import mir.bundle.Bundle;
32 import mir.config.MirPropertiesConfiguration;
33 import mir.servlet.*;
34 import mir.util.ExceptionFunctions;
35 import mir.util.StringRoutines;
36 import mir.log.LoggerWrapper;
37 import mircoders.entity.EntityUsers;
38 import mircoders.global.MirGlobal;
39 import mircoders.module.ModuleUsers;
40 import mircoders.servlet.ServletHelper;
41
42 import javax.servlet.ServletConfig;
43 import javax.servlet.ServletException;
44 import javax.servlet.UnavailableException;
45 import javax.servlet.http.*;
46 import java.io.IOException;
47 import java.io.PrintWriter;
48 import java.lang.reflect.Method;
49 import java.util.*;
50
51 /**
52  * Mir.java - main servlet, that dispatches to servletmodules
53  *
54  * @author $Author: idfx $
55  *
56  */
57 public class Mir extends AbstractServlet {
58   private static ModuleUsers usersModule = null;
59   private final static Map servletModuleInstanceHash = new HashMap();
60   private static Locale fallbackLocale = null;
61
62   private static List loginLanguages = null;
63
64   protected List getLoginLanguages() throws ServletException {
65     synchronized (Mir.class) {
66       try {
67         if (loginLanguages == null) {
68           List languages =
69             StringRoutines.splitString(MirGlobal.config().getString("Mir.Login.Languages", "en"), ";");
70
71           loginLanguages = new ArrayList();
72
73           Iterator i = languages.iterator();
74
75           while (i.hasNext()) {
76             String code = (String) i.next();
77
78             Bundle bundle =
79                 MirGlobal.getBundleFactory().getBundle("etc/bundles/adminlocal", new String[] { code });
80             Bundle defaultBundle =
81                 MirGlobal.getBundleFactory().getBundle("bundles/admin", new String[] { code });
82
83             String name = bundle.getValue("languagename", Collections.EMPTY_LIST);
84
85             if (name == null) {
86               name = defaultBundle.getValue("languagename", Collections.EMPTY_LIST);
87             }
88
89             if (name == null) {
90               name = code;
91             }
92
93             Map record = new HashMap();
94             record.put("name", name);
95             record.put("code", code);
96             loginLanguages.add(record);
97           }
98         }
99
100         return loginLanguages;
101       }
102       catch (Throwable t) {
103         throw new ServletException(t.getMessage());
104       }
105     }
106   }
107
108   public void init(ServletConfig config) throws ServletException {
109     super.init(config);
110
111     usersModule = new ModuleUsers();
112   }
113
114   protected String getDefaultLanguage(HttpServletRequest aRequest) {
115     String defaultlanguage =
116       MirGlobal.config().getString("Mir.Login.DefaultLanguage", "");
117
118     if (defaultlanguage.length() == 0) {
119       Locale locale = aRequest.getLocale();
120       defaultlanguage = locale.getLanguage();
121     }
122
123     return defaultlanguage;
124   }
125
126   protected synchronized Locale getFallbackLocale() throws ServletException {
127     try {
128       if (fallbackLocale == null) {
129         fallbackLocale = new Locale(MirPropertiesConfiguration.instance().getString("Mir.Admin.FallbackLanguage", "en"), "");
130       }
131     }
132     catch (Throwable t) {
133       throw new ServletException(t.getMessage());
134     }
135
136     return fallbackLocale;
137   }
138
139   public EntityUsers checkCredentials(HttpServletRequest aRequest) throws ServletException {
140     try {
141       EntityUsers user = ServletHelper.getUser(aRequest);
142
143       String username = aRequest.getParameter("login");
144       String password = aRequest.getParameter("password");
145
146       if (username != null && password != null) {
147         user = usersModule.getUserForLogin(username, password);
148
149         if (user!=null) {
150           ServletHelper.setUser(aRequest, user);
151           usersModule.recordLogin(user);
152           aRequest.getSession().setAttribute("sessiontracker", new SessionTracker(username, user.getId()));
153         }
154       }
155
156       return user;
157     }
158     catch (Throwable t) {
159       t.printStackTrace();
160
161       throw new ServletException(t.toString());
162     }
163   }
164
165   public void process(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletException, IOException, UnavailableException {
166     try {
167       long startTime = System.currentTimeMillis();
168       long sessionConnectTime = 0;
169
170       HttpSession session = aRequest.getSession(true);
171       setNoCaching(aResponse);
172       aResponse.setContentType("text/html; charset=" +
173                                configuration.
174                                getString("Mir.DefaultHTMLCharset", "UTF-8"));
175
176       EntityUsers userEntity = checkCredentials(aRequest);
177
178       if (userEntity == null) {
179         String queryString = aRequest.getQueryString();
180
181         if ( (queryString != null) && (queryString.length() != 0) && session.getAttribute("login.target") == null &&
182              (aRequest.getParameter("module")==null ||
183               (!aRequest.getParameter("module").equals("login") && !aRequest.getParameter("module").equals("logout")))) {
184           session.setAttribute("login.target", queryString);
185         }
186
187         _sendLoginPage(aResponse, aRequest);
188       }
189       else {
190         String moduleName = aRequest.getParameter("module");
191         checkLanguage(session, aRequest);
192
193         if ( ( (moduleName == null) || moduleName.equals(""))) {
194           moduleName="Admin";
195         }
196
197
198         if (moduleName.equals("login")) {
199           String target = (String) session.getAttribute("login.target");
200
201           if (target != null) {
202             ServletHelper.redirect(aResponse, target);
203           }
204           else {
205             ServletHelper.redirect(aResponse, "");
206           }
207         }
208         else if (moduleName.equals("logout")) {
209           logger.info(userEntity.getFieldValue("login") + " has logged out");
210           session.invalidate();
211           _sendLoginPage(aResponse, aRequest);
212           return;
213         }
214         else {
215           try {
216             ServletModule servletModule = getServletModuleForName(moduleName);
217             ServletModuleDispatch.dispatch(servletModule, aRequest, aResponse);
218
219             sessionConnectTime = System.currentTimeMillis() - startTime;
220             logger.info("EXECTIME (" + moduleName + "): " + sessionConnectTime + " ms");
221           }
222           catch (Throwable e) {
223             Throwable cause = ExceptionFunctions.traceCauseException(e);
224
225             if (cause instanceof ServletModuleUserExc)
226               handleUserError(aRequest, aResponse, (ServletModuleUserExc) cause);
227             else
228               handleError(aRequest, aResponse, cause);
229           }
230
231           if (aRequest.getParameter("killsession")!=null)
232             aRequest.getSession().invalidate();
233         }
234       }
235     }
236     catch (Throwable t) {
237       t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
238
239       throw new ServletException(t.toString());
240     }
241   }
242
243   /**
244    * caching routine to get a module for a module name
245    *
246    * @param moduleName the module name
247    * @return the requested module
248    * @throws ServletModuleExc
249    */
250
251   private static ServletModule getServletModuleForName(String moduleName) throws ServletModuleExc {
252     // Instance in Map ?
253     if (!servletModuleInstanceHash.containsKey(moduleName)) {
254       // was not found in hash...
255       try {
256         Class theServletModuleClass = null;
257
258         try {
259           // first we try to get ServletModule from stern.che3.servlet
260           theServletModuleClass =
261             Class.forName("mircoders.servlet.ServletModule" + moduleName);
262         }
263         catch (ClassNotFoundException e) {
264           // on failure, we try to get it from lib-layer
265           theServletModuleClass =
266             Class.forName("mir.servlet.ServletModule" + moduleName);
267         }
268
269         Method m = theServletModuleClass.getMethod("getInstance", null);
270         ServletModule smod = (ServletModule) m.invoke(null, null);
271
272         // we put it into map for further reference
273         servletModuleInstanceHash.put(moduleName, smod);
274
275         return smod;
276       }
277       catch (Exception e) {
278         throw new ServletModuleExc("*** error resolving classname for " + moduleName + " -- " + e.getMessage());
279       }
280     }
281     else {
282       return (ServletModule) servletModuleInstanceHash.get(moduleName);
283     }
284   }
285
286   private void handleUserError(HttpServletRequest aRequest, HttpServletResponse aResponse, ServletModuleUserExc anException) {
287     try {
288       logger.info("user error: " + anException.getMessage());
289
290       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale()});
291
292       Bundle bundle =
293           MirGlobal.getBundleFactory().getBundle("etc/bundles/adminlocal", new
294               String[] { getLocale(aRequest).getLanguage() });
295       Bundle defaultBundle =
296           MirGlobal.getBundleFactory().getBundle("bundles/admin", new
297               String[] { getLocale(aRequest).getLanguage() });
298       String message =
299         bundle.getValue(anException.getMessage(), Arrays.asList(anException.getParameters()));
300
301       if (message==null) {
302         message =
303           defaultBundle.getValue(anException.getMessage(), Arrays.asList(anException.getParameters()));
304       }
305
306       responseData.put("errorstring", message);
307       responseData.put("date", new GregorianCalendar().getTime());
308
309       ServletHelper.generateResponse(aResponse.getWriter(), responseData, MirPropertiesConfiguration.instance().getString("Mir.UserErrorTemplate"));
310     }
311     catch (Throwable e) {
312       logger.error("Error handling user error" + e.toString());
313     }
314   }
315
316   private void handleError(HttpServletRequest aRequest, HttpServletResponse aResponse, Throwable anException) {
317     try {
318       logger.error("error: " + anException);
319
320       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale()});
321
322       responseData.put("errorstring", anException.toString());
323       responseData.put("date", new GregorianCalendar().getTime());
324
325       ServletHelper.generateResponse(aResponse.getWriter(), responseData, MirPropertiesConfiguration.instance().getString("Mir.ErrorTemplate"));
326     }
327     catch (Throwable e) {
328       logger.error("Error handling error: " + e.toString());
329
330       try {
331         Throwable rootException = ExceptionFunctions.traceCauseException(anException);
332
333         PrintWriter writer = aResponse.getWriter();
334         writer.println("<html><head><title>FATAL Error</title><body>");
335         writer.println("<h1>" + rootException.toString()+"</h1>");
336         writer.println("<code>");
337         rootException.printStackTrace(writer);
338         writer.println("</code>");
339         writer.println("</body></html>");
340         writer.close();
341       }
342       catch (Throwable t) {
343
344       }
345     }
346   }
347
348   // Redirect-methods
349   private void _sendLoginPage(HttpServletResponse aResponse, HttpServletRequest aRequest) {
350     String loginTemplate = configuration.getString("Mir.LoginTemplate");
351
352     try {
353       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale()});
354
355       responseData.put("defaultlanguage", getDefaultLanguage(aRequest));
356       responseData.put("languages", getLoginLanguages());
357
358       ServletHelper.generateResponse(aResponse.getWriter(), responseData, loginTemplate);
359     }
360     catch (Throwable e) {
361       handleError(aRequest, aResponse, e);
362     }
363   }
364
365   public String getServletInfo() {
366     return "Mir " + configuration.getString("Mir.Version");
367   }
368
369   private class SessionTracker implements HttpSessionBindingListener {
370     private String name;
371     private String id;
372
373     public SessionTracker(String aUserName, String anId) {
374       name = aUserName;
375       id = anId;
376     }
377
378     public void valueBound(HttpSessionBindingEvent anEvent) {
379       MirGlobal.registerLogin(name, id);
380     }
381
382     public void valueUnbound(HttpSessionBindingEvent anEvent) {
383       MirGlobal.registerLogout(name, id);
384     }
385   }
386 }