Clover Coverage Report - itracker
Coverage timestamp: Tue May 1 2012 16:42:12 CEST
185   490   64   15.42
86   361   0.35   12
12     5.33  
1    
 
 
  ExecuteAlwaysFilter       Line # 49 185 64 0% 0.0
 
No Tests
 
1    package org.itracker.web.filters;
2   
3    import java.io.IOException;
4    import java.util.HashSet;
5    import java.util.Iterator;
6    import java.util.Locale;
7    import java.util.Map;
8    import java.util.Set;
9    import java.util.StringTokenizer;
10    import java.util.regex.Pattern;
11   
12    import javax.servlet.Filter;
13    import javax.servlet.FilterChain;
14    import javax.servlet.FilterConfig;
15    import javax.servlet.ServletException;
16    import javax.servlet.ServletRequest;
17    import javax.servlet.ServletResponse;
18    import javax.servlet.http.HttpServletRequest;
19    import javax.servlet.http.HttpServletResponse;
20    import javax.servlet.http.HttpSession;
21   
22    import org.apache.log4j.Logger;
23    import org.apache.struts.Globals;
24    import org.apache.struts.action.ActionForward;
25    import org.apache.struts.action.ActionMessage;
26    import org.apache.struts.action.ActionMessages;
27    import org.itracker.core.resources.ITrackerResources;
28    import org.itracker.model.PermissionType;
29    import org.itracker.model.User;
30    import org.itracker.services.ConfigurationService;
31    import org.itracker.services.ITrackerServices;
32    import org.itracker.services.util.UserUtilities;
33    import org.itracker.web.util.Constants;
34    import org.itracker.web.util.LoginUtilities;
35    import org.itracker.web.util.RequestHelper;
36    import org.itracker.web.util.ServletContextUtils;
37    import org.itracker.web.util.SessionManager;
38   
39    /**
40    * Configurations:
41    * <ul>
42    * <li>AuthExcludedPaths: Comma separated list of Regex url-Patterns (eg.
43    * <code>/login.do, /unprotected-path/**</code>)</li>
44    * </ul>
45    *
46    * @author ranks
47    *
48    */
 
49    public class ExecuteAlwaysFilter implements Filter {
50   
51    /**
52    * Logger for ExecuteAlwaysFilter
53    */
54    private static final Logger log = Logger
55    .getLogger(ExecuteAlwaysFilter.class);
56    private static final String DEFAULT_LOGIN_FORWARD = "/login.do";
57    /**
58    * Name for session key for forward after successful authentication.
59    */
60    private static final String SES_KEY_REDIRECT_ON_SUCCESS = ExecuteAlwaysFilter.class
61    .getName()
62    + "/REDIRECT_ON_SUCCESS";
63   
64    private ITrackerServices iTrackerServices;
65    /**
66    * this match paths which are not protected
67    */
68    private Set<Pattern> unprotectedPaterns = null;
69   
70    private String loginForwardPath;
71   
 
72  0 toggle public void destroy() {
73  0 this.unprotectedPaterns = null;
74    }
75   
 
76  0 toggle public void doFilter(ServletRequest servletRequest,
77    ServletResponse response, FilterChain chain) throws IOException,
78    ServletException {
79  0 if (null == this.unprotectedPaterns) {
80  0 RuntimeException re = new IllegalStateException(
81    "Filter has not been initialized yet.");
82  0 log.error("doFilter: failed, not initialized", re);
83  0 throw re;
84    }
85   
86  0 if (!(servletRequest instanceof HttpServletRequest)) {
87  0 RuntimeException re = new IllegalArgumentException(
88    "Usupported servlet-request of type: "
89    + servletRequest.getClass().getName());
90  0 log.error("doFilter: failed, invalid request type", re);
91  0 throw re;
92    }
93   
94  0 HttpServletRequest request = (HttpServletRequest) servletRequest;
95   
96  0 String path = request.getRequestURI().substring(
97    request.getContextPath().length());
98  0 if (log.isDebugEnabled()) {
99  0 log.debug("doFilter: called with path " + path);
100    }
101   
102    // From IrackerBaseAction.executeAlways
103  0 if (log.isDebugEnabled()) {
104  0 log
105    .debug("doFilter: setting the common request attributes, (coming from the former header.jsp)");
106    }
107  0 ConfigurationService configurationService = getITrackerServices()
108    .getConfigurationService();
109   
110  0 boolean protect = isProtected(path, this.unprotectedPaterns);
111   
112    // do not protect the login-page itself.
113  0 if (protect && this.loginForwardPath.equals(path)) {
114  0 protect = false;
115    }
116   
117  0 if (log.isDebugEnabled()) {
118  0 log.debug("doFilter: protecting '" + path + "': " + protect);
119    }
120   
121   
122   
123  0 User currUser = LoginUtilities.getCurrentUser(request);
124   
125  0 if (null == currUser && protect) {
126    // check for autologin
127  0 if (LoginUtilities.checkAutoLogin(request, configurationService.getBooleanProperty(
128    "allow_save_login", true))) {
129   
130  0 String login = String.valueOf(request.getAttribute(Constants.AUTH_LOGIN_KEY));
131  0 currUser = LoginUtilities.setupSession(login, request, (HttpServletResponse)response);
132   
133  0 try {
134  0 SessionManager.createSession(login);
135    } catch (Exception e) {
136  0 handleError(e, request, response);
137    }
138   
139    }
140    }
141   
142  0 setupCommonReqAttributes(request, configurationService);
143   
144  0 if (null != currUser) {
145  0 if (log.isDebugEnabled()) {
146  0 log.debug("doFilter: found user in session");
147    }
148  0 String currLogin = currUser.getLogin();
149   
150  0 log.info("Login found...: " + currLogin);
151  0 if (SessionManager.getSessionNeedsReset(currLogin)) {
152    // RESET THE SESSION STUFF
153  0 HttpSession session = request.getSession();
154  0 log.info("Resetting the Session stuff...");
155  0 session.removeAttribute(Constants.USER_KEY);
156  0 session.removeAttribute(Constants.PERMISSIONS_KEY);
157  0 currUser = null;
158  0 String newLogin = SessionManager.checkRenamedLogin(currLogin);
159  0 if (response instanceof HttpServletResponse) {
160  0 currUser = LoginUtilities.setupSession((newLogin == null ? currLogin
161    : newLogin), request, (HttpServletResponse)response);
162    }
163  0 SessionManager.removeRenamedLogin(currLogin);
164  0 if (currUser == null
165    || currUser.getStatus() != UserUtilities.STATUS_ACTIVE) {
166  0 ActionMessages errors = new ActionMessages();
167  0 errors.add(ActionMessages.GLOBAL_MESSAGE,
168    new ActionMessage(
169    "itracker.web.error.login.inactive"));
170  0 saveErrors(request, errors);
171    // request.setAttribute(Globals.ERROR_KEY, errors);
172   
173  0 log.info("doFilter: forwarding to login");
174  0 forwardToLogin(path
175  0 + (request.getQueryString() != null ? "?"
176    + request.getQueryString() : ""), request,
177    (HttpServletResponse) response);
178    }
179    }
180   
181  0 request.setAttribute("currLogin", currLogin);
182  0 } else if (!protect) {
183    // request.setAttribute("permissions", permissions);
184    // TODO: itracker.web.generic.unknown for unknown user?
185  0 request.setAttribute("currLogin", ITrackerResources
186    .getString("itracker.web.header.guest"));
187    } else {
188    // unauthenticated.. forward to login
189  0 log.info("doFilter: forwarding to login");
190  0 forwardToLogin(path
191  0 + (request.getQueryString() != null ? "?"
192    + request.getQueryString() : ""), request,
193    (HttpServletResponse) response);
194  0 return;
195    }
196  0 setupCommonReqAttributesEx(request);
197  0 try {
198  0 if (log.isDebugEnabled()) {
199  0 log.info("doFilter: executing chain..");
200    }
201  0 chain.doFilter(request, response);
202   
203  0 if (log.isDebugEnabled()) {
204  0 log.info("doFilter: completed chain execution.");
205    }
206    } catch (RuntimeException e) {
207  0 log.error(
208    "doFilter: failed to execute chain with runtime exception: "
209    + e.getMessage(), e);
210  0 handleError(e, request, response);
211   
212    } catch (IOException ioe) {
213  0 log.error("doFilter: failed to execute chain with i/o exception: "
214    + ioe.getMessage(), ioe);
215  0 handleError(ioe, request, response);
216   
217    } catch (ServletException se) {
218  0 log.error(
219    "doFilter: failed to execute chain with servlet exception: "
220    + se.getMessage(), se);
221  0 handleError(se, request, response);
222   
223    } catch (Error err) {
224  0 log.fatal("doFilter: caught fatal error executing filter chain",
225    err);
226  0 throw err;
227    }
228    }
229   
 
230  0 toggle private final void handleError(Throwable error, ServletRequest request, ServletResponse response) throws ServletException {
231   
232  0 if (null == error) {
233  0 log.info("handleError: called with null throwable");
234  0 error = new RuntimeException(error);
235    }
236   
237  0 log.info("handleError: called with " + error.getClass().getSimpleName(), error);
238   
239  0 if (!(response instanceof HttpServletResponse) || !(request instanceof HttpServletRequest)) {
240  0 log.error("handleError: unknown request/response: " + request + ", " + response, error);
241  0 throw new ServletException(error.getMessage(), error);
242    }
243  0 HttpServletRequest httpRequest = (HttpServletRequest) request;
244  0 HttpServletResponse httpResponse = (HttpServletResponse) response;
245   
246  0 ActionMessages errors = new ActionMessages();
247  0 errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("itracker.web.error.system.message",
248  0 new Object[]{error.getLocalizedMessage() == null ? error.getMessage() : error.getLocalizedMessage(),
249    error.getClass().getCanonicalName()}));
250   
251  0 saveErrors((HttpServletRequest)request, errors);
252  0 try {
253    // response.sendError(500, "Internal Server Error");
254  0 httpResponse.sendRedirect(httpRequest.getContextPath() + "/error.do");
255    } catch (IOException e) {
256  0 log.fatal("handleError: failed to redirect to error-page");
257  0 return;
258    }
259    }
260   
261    /**
262    * <p>Save the specified error messages keys into the appropriate request
263    * attribute for use by the &lt;html:errors&gt; tag, if any messages
264    * are required. Otherwise, ensure that the request attribute is not
265    * created.</p>
266    *
267    * @param request The servlet request we are processing
268    * @param errors Error messages object
269    * @since Struts 1.2
270    */
 
271  0 toggle protected void saveErrors(HttpServletRequest request, ActionMessages errors) {
272   
273    // Remove any error messages attribute if none are required
274  0 if ((errors == null) || errors.isEmpty()) {
275  0 request.removeAttribute(Globals.ERROR_KEY);
276  0 request.getSession().removeAttribute(Globals.ERROR_KEY);
277  0 return;
278    }
279   
280  0 if (log.isInfoEnabled()) {
281  0 log.info("saveErrors: saved errors: " + errors);
282    }
283    // Save the error messages we need
284  0 request.setAttribute(Globals.ERROR_KEY, errors);
285   
286  0 request.getSession().setAttribute(Globals.ERROR_KEY, errors);
287    }
288   
289   
 
290  0 toggle private static final void setupCommonReqAttributes(
291    HttpServletRequest request,
292    ConfigurationService configurationService) {
293  0 boolean allowForgotPassword = true;
294  0 boolean allowSelfRegister = false;
295  0 boolean allowSaveLogin = true;
296  0 String alternateLogo = null;
297   
298  0 allowForgotPassword = configurationService.getBooleanProperty(
299    "allow_forgot_password", true);
300  0 allowSelfRegister = configurationService.getBooleanProperty(
301    "allow_self_register", false);
302  0 allowSaveLogin = configurationService.getBooleanProperty(
303    "allow_save_login", true);
304  0 alternateLogo = configurationService
305    .getProperty("alternate_logo", null);
306  0 Locale locale = LoginUtilities.getCurrentLocale(request);
307   
308    // TODO: this should be configured per-instance. Request server-name
309    // should only be used for exception and logged (configuration not
310    // found!)
311   
312  0 String baseURL = configurationService.getSystemBaseURL();
313  0 if (null == baseURL) {
314  0 baseURL = request.getScheme() + "://" + request.getServerName()
315    + ":" + request.getServerPort() + request.getContextPath();
316  0 log.warn("setupCommonReqAttributes: not found system_base_url configuration, setting from request: " + baseURL);
317    }
318  0 request.setAttribute("allowForgotPassword", Boolean
319    .valueOf(allowForgotPassword));
320  0 request.setAttribute("allowSelfRegister", Boolean
321    .valueOf(allowSelfRegister));
322  0 request.setAttribute("allowSaveLogin", Boolean.valueOf(allowSaveLogin));
323  0 request.setAttribute("alternateLogo", alternateLogo);
324  0 request.setAttribute("baseURL", baseURL);
325    // TODO: remove deprecated currLocale attribute
326  0 request.setAttribute("currLocale", locale);
327   
328    // set a default page-title key
329  0 request.setAttribute("pageTitleKey", "itracker.web.generic.itracker");
330  0 request.setAttribute("pageTitleArg", "");
331   
332   
333  0 request.setAttribute("locales", configurationService.getAvailableLanguages());
334   
335   
336  0 request.setAttribute(Constants.LOCALE_KEY, locale);
337   
338   
339    }
340   
 
341  0 toggle private static final void setupCommonReqAttributesEx(HttpServletRequest request) {
342  0 final Map<Integer, Set<PermissionType>> permissions = RequestHelper
343    .getUserPermissions(request.getSession());
344  0 request.setAttribute("hasPermissionUserAdmin", UserUtilities.hasPermission(permissions,
345    UserUtilities.PERMISSION_USER_ADMIN));
346  0 request.setAttribute("hasPermissionProductAdmin", UserUtilities.hasPermission(permissions,
347    UserUtilities.PERMISSION_PRODUCT_ADMIN));
348  0 request.setAttribute("contextPath", request.getContextPath());
349   
350  0 request.setAttribute("currentDate", new java.util.Date());
351    }
352   
353   
 
354  0 toggle private static final boolean isProtected(String path, Set<Pattern> patterns) {
355  0 if (null == path) {
356  0 path = "";
357    }
358   
359  0 Iterator<Pattern> matchPattern = patterns.iterator();
360  0 Pattern pattern;
361   
362  0 while (matchPattern.hasNext()) {
363  0 pattern = matchPattern.next();
364  0 if (log.isDebugEnabled()) {
365  0 log.debug("isProtected: processing path " + path
366    + " for pattern " + pattern.pattern());
367    }
368  0 if (pattern.matcher(path).matches()) {
369  0 if (log.isDebugEnabled()) {
370  0 log.debug("isProtected: matched path: " + path);
371    }
372  0 return false;
373    }
374    }
375   
376  0 if (log.isDebugEnabled()) {
377  0 log.debug("isProtected: protecting " + path);
378    }
379  0 return true;
380    }
381   
382   
383   
384    /**
385    *
386    */
 
387  0 toggle public void init(FilterConfig filterConfig) throws ServletException {
388  0 if (null != unprotectedPaterns) {
389  0 throw new IllegalStateException(
390    "Filter was already initialized before.");
391    }
392  0 String excludePaths = filterConfig
393    .getInitParameter("AuthExcludedPaths");
394   
395  0 this.loginForwardPath = filterConfig.getInitParameter("LoginForward");
396  0 if (null == this.loginForwardPath) {
397  0 this.loginForwardPath = DEFAULT_LOGIN_FORWARD;
398    }
399  0 this.unprotectedPaterns = new HashSet<Pattern>();
400  0 if (null != excludePaths) {
401  0 StringTokenizer tk = new StringTokenizer(excludePaths, ",");
402  0 while (tk.hasMoreTokens()) {
403  0 this.unprotectedPaterns.add(Pattern.compile(tk.nextToken().trim()));
404    }
405    }
406  0 if (log.isInfoEnabled()) {
407  0 log.info("init: initialized with " + this.loginForwardPath
408    + ", excludes: " + this.unprotectedPaterns);
409    }
410    }
411   
 
412  0 toggle public ITrackerServices getITrackerServices() {
413  0 if (null == this.iTrackerServices) {
414   
415  0 this.iTrackerServices = ServletContextUtils.getItrackerServices();
416    }
417  0 return iTrackerServices;
418    }
419   
420    /**
421    *
422    *
423    *
424    * @param request
425    * @param response
426    * @param thisactionforward
427    * @return String - outcome
428    */
 
429  0 toggle private void forwardToLogin(String path, HttpServletRequest request,
430    HttpServletResponse response) {
431  0 if (log.isDebugEnabled()) {
432  0 log.debug("forwardToLogin: called with " + path + " request: "
433    + request + " response: " + response);
434    }
435  0 String forwardPath = request.getContextPath() + this.loginForwardPath;
436  0 if (log.isDebugEnabled()) {
437  0 log
438    .debug("forwardToLogin: (formerly Checklogin tag) procedure... to "
439    + forwardPath);
440    }
441  0 HttpSession session = request.getSession();
442  0 try {
443   
444  0 log.info("forwardToLogin: setting redirectURL "
445    + SES_KEY_REDIRECT_ON_SUCCESS + " = " + path);
446  0 session.setAttribute(SES_KEY_REDIRECT_ON_SUCCESS, path);
447  0 session.setAttribute("loginForwarded", true);
448  0 response.sendRedirect(forwardPath);
449  0 response.flushBuffer();
450   
451    } catch (Exception e) {
452  0 log.error("forwardToLogin: IOException while checking login", e);
453  0 response.reset();
454  0 try {
455  0 session.setAttribute("loginForwarded", Boolean.TRUE);
456  0 response.sendRedirect(forwardPath);
457    } catch (IOException e1) {
458  0 log.error("forwardToLogin: failed to redirect to "
459    + forwardPath, e1);
460    }
461    }
462    }
463   
 
464  0 toggle public static void redirectToOnLoginSuccess(HttpServletRequest request,
465    HttpServletResponse response) throws IOException {
466  0 String path = (String) request.getSession().getAttribute(
467    SES_KEY_REDIRECT_ON_SUCCESS);
468  0 if (null == path) {
469  0 path = "/";
470    }
471  0 if (log.isDebugEnabled()) {
472  0 log.debug("redirectToOnLoginSuccess: sending redirect to " + path);
473    }
474  0 response.sendRedirect(path);
475    }
476   
 
477  0 toggle public static ActionForward forwardToOnLoginSuccess(
478    HttpServletRequest request, HttpServletResponse response)
479    throws IOException {
480  0 String path = (String) request.getSession().getAttribute(
481    SES_KEY_REDIRECT_ON_SUCCESS);
482  0 if (null == path) {
483  0 path ="/";
484    }
485  0 if (log.isDebugEnabled()) {
486  0 log.debug("redirectToOnLoginSuccess: sending redirect to " + path);
487    }
488  0 return new ActionForward(path, true);
489    }
490    }