info.jtrac.wicket.JtracApplication.java Source code

Java tutorial

Introduction

Here is the source code for info.jtrac.wicket.JtracApplication.java

Source

/*
 * Copyright 2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package info.jtrac.wicket;

import info.jtrac.acegi.JtracCasProxyTicketValidator;
import info.jtrac.domain.Role;
import info.jtrac.domain.Space;
import info.jtrac.domain.User;
import info.jtrac.service.Jtrac;
import info.jtrac.util.WebUtils;
import info.jtrac.wicket.devmode.DebugHttpSessionStore;

import java.util.List;
import java.util.Locale;

import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;

import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.Request;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.Response;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.Session;
import org.apache.wicket.authorization.Action;
import org.apache.wicket.authorization.IAuthorizationStrategy;
import org.apache.wicket.markup.html.pages.RedirectPage;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.request.target.coding.IndexedParamUrlCodingStrategy;
import org.apache.wicket.request.target.coding.QueryStringUrlCodingStrategy;
import org.apache.wicket.resource.loader.IStringResourceLoader;
import org.apache.wicket.session.ISessionStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * <p>
 * Main Wicket application for jtrac.
 * </p>
 * <p>
 * It holds singleton service layer instance pulled from Spring.
 * </p>
 */
public class JtracApplication extends WebApplication {
    /**
     * Logger object
     */
    private final static Logger logger = LoggerFactory.getLogger(JtracApplication.class);

    private Jtrac jtrac;
    private ApplicationContext applicationContext;
    private JtracCasProxyTicketValidator jtracCasProxyTicketValidator;

    public Jtrac getJtrac() {
        return jtrac;
    }

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * This method will the login URL and is used only by CasLoginPage.
     *
     * @return Returns login URL.
     */
    public String getCasLoginUrl() {
        if (jtracCasProxyTicketValidator == null) {
            return null;
        }
        return jtracCasProxyTicketValidator.getLoginUrl();
    }

    /**
     * This method will the logout URL and is used only by logout link
     * in HeaderPanel.
     *
     * @return Returns logout URL.
     */
    public String getCasLogoutUrl() {
        if (jtracCasProxyTicketValidator == null) {
            return null;
        }
        return jtracCasProxyTicketValidator.getLogoutUrl();
    }

    /**
     * This method will return the main JtracApplication object.
     *
     * @return Returns JtracApplication object.
     */
    public static JtracApplication get() {
        return (JtracApplication) Application.get();
    }

    /* (non-Javadoc)
     * @see org.apache.wicket.protocol.http.WebApplication#init()
     */
    @Override
    public void init() {
        super.init();

        /*
         * Get hold of spring managed service layer (see BasePage, BasePanel,
         * etc. for how it is used).
         */
        ServletContext sc = getServletContext();
        applicationContext = WebApplicationContextUtils.getWebApplicationContext(sc);
        jtrac = (Jtrac) applicationContext.getBean("jtrac");

        /*
         * Check if acegi-cas authentication is being used, get reference to
         * object to be used by Wicket authentication to redirect to right
         * pages for login/logout.
         */
        try {
            jtracCasProxyTicketValidator = (JtracCasProxyTicketValidator) applicationContext
                    .getBean("casProxyTicketValidator");
            logger.info("casProxyTicketValidator retrieved from application " + "context: "
                    + jtracCasProxyTicketValidator);
        } catch (NoSuchBeanDefinitionException nsbde) {
            logger.debug(nsbde.getMessage());
            logger.info("casProxyTicketValidator not found in application "
                    + "context, CAS single-sign-on is not being used");
        }

        /*
         * Delegate Wicket i18n support to spring i18n
         */
        getResourceSettings().addStringResourceLoader(new IStringResourceLoader() {
            /* (non-Javadoc)
            * @see org.apache.wicket.resource.loader.IStringResourceLoader#loadStringResource(java.lang.Class, java.lang.String, java.util.Locale, java.lang.String)
            */
            @Override
            public String loadStringResource(@SuppressWarnings("rawtypes") Class clazz, String key, Locale locale,
                    String style) {
                try {
                    return applicationContext.getMessage(key, null,
                            locale == null ? Session.get().getLocale() : locale);
                } catch (Exception e) {
                    /*
                     * For performance, Wicket expects null instead of
                     * throwing an exception and Wicket may try to
                     * re-resolve using prefixed variants of the key.
                     */
                    return null;
                }
            }

            /* (non-Javadoc)
            * @see org.apache.wicket.resource.loader.IStringResourceLoader#loadStringResource(org.apache.wicket.Component, java.lang.String)
            */
            @Override
            public String loadStringResource(Component component, String key) {
                String value = loadStringResource(null, key, component == null ? null : component.getLocale(),
                        null);
                if (logger.isDebugEnabled() && value == null) {
                    logger.debug("i18n failed for key: '" + key + "', component: " + component);
                }
                return value;
            }
        });

        getSecuritySettings().setAuthorizationStrategy(new IAuthorizationStrategy() {
            /* (non-Javadoc)
            * @see org.apache.wicket.authorization.IAuthorizationStrategy#isActionAuthorized(org.apache.wicket.Component, org.apache.wicket.authorization.Action)
            */
            @Override
            public boolean isActionAuthorized(Component c, Action a) {
                return true;
            }

            /* (non-Javadoc)
            * @see org.apache.wicket.authorization.IAuthorizationStrategy#isInstantiationAuthorized(java.lang.Class)
            */
            @Override
            public boolean isInstantiationAuthorized(@SuppressWarnings("rawtypes") Class clazz) {
                if (BasePage.class.isAssignableFrom(clazz)) {
                    if (JtracSession.get().isAuthenticated()) {
                        return true;
                    }
                    if (jtracCasProxyTicketValidator != null) {
                        /*
                         * ============================================
                         * Attempt CAS authentication
                         * ============================================
                         */
                        logger.debug("checking if context contains CAS authentication");
                        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                        if (authentication != null && authentication.isAuthenticated()) {
                            logger.debug("security context contains CAS authentication, initializing session");
                            JtracSession.get().setUser((User) authentication.getPrincipal());
                            return true;
                        }
                    }

                    /*
                     * ================================================
                     * Attempt remember-me auto login
                     * ================================================
                     */
                    if (attemptRememberMeAutoLogin()) {
                        return true;
                    }

                    /*
                     * =================================================
                     * Attempt guest access if there are "public" spaces
                     * =================================================
                     */
                    List<Space> spaces = getJtrac().findSpacesWhereGuestAllowed();
                    if (spaces.size() > 0) {
                        logger.debug(spaces.size() + " public space(s) available, initializing guest user");
                        User guestUser = new User();
                        guestUser.setLoginName("guest");
                        guestUser.setName("Guest");
                        for (Space space : spaces) {
                            guestUser.addSpaceWithRole(space, Role.ROLE_GUEST);
                        }

                        JtracSession.get().setUser(guestUser);
                        // and proceed
                        return true;
                    }

                    /*
                     * Not authenticated, go to login page.
                     */
                    logger.debug("not authenticated, forcing login, " + "page requested was " + clazz.getName());
                    if (jtracCasProxyTicketValidator != null) {
                        String serviceUrl = jtracCasProxyTicketValidator.getServiceProperties().getService();
                        String loginUrl = jtracCasProxyTicketValidator.getLoginUrl();
                        logger.debug("cas authentication: service URL: " + serviceUrl);
                        String redirectUrl = loginUrl + "?service=" + serviceUrl;
                        logger.debug("attempting to redirect to: " + redirectUrl);
                        throw new RestartResponseAtInterceptPageException(new RedirectPage(redirectUrl));
                    } else {
                        throw new RestartResponseAtInterceptPageException(LoginPage.class);
                    }
                }
                return true;
            }
        });

        /*
         * Friendly URLs for selected pages
         */
        if (jtracCasProxyTicketValidator != null) {
            mountBookmarkablePage("/login", CasLoginPage.class);
            /*
             * This matches the value set in:
             * WEB-INF/applicationContext-acegi-cas.xml
             */
            mountBookmarkablePage("/cas/error", CasLoginErrorPage.class);
        } else {
            mountBookmarkablePage("/login", LoginPage.class);
        }

        mountBookmarkablePage("/logout", LogoutPage.class);
        mountBookmarkablePage("/svn", SvnStatsPage.class);
        mountBookmarkablePage("/options", OptionsPage.class);
        mountBookmarkablePage("/item/form", ItemFormPage.class);

        /*
         * Bookmarkable URL for search and search results
         */
        mount(new QueryStringUrlCodingStrategy("/item/search", ItemSearchFormPage.class));
        mount(new QueryStringUrlCodingStrategy("/item/list", ItemListPage.class));

        /*
         * Bookmarkable URL for viewing items
         */
        mount(new IndexedParamUrlCodingStrategy("/item", ItemViewPage.class));
    }

    /* (non-Javadoc)
     * @see org.apache.wicket.protocol.http.WebApplication#newSession(org.apache.wicket.Request, org.apache.wicket.Response)
     */
    @Override
    public JtracSession newSession(Request request, Response response) {
        return new JtracSession(request);
    }

    /* (non-Javadoc)
     * @see org.apache.wicket.protocol.http.WebApplication#newSessionStore()
     */
    @Override
    protected ISessionStore newSessionStore() {
        if (getConfigurationType().equalsIgnoreCase(DEVELOPMENT)) {
            logger.warn("wicket development mode, using custom debug http session store");

            /*
             * The default second level cache session store does not play well
             * with our custom reloading filter so we use a custom session store.
             */
            return new DebugHttpSessionStore(this);
        } else {
            ISessionStore sessionStore = super.newSessionStore();
            logger.info("wicket production mode, using: " + sessionStore);
            return sessionStore;
        }
    }

    /* (non-Javadoc)
     * @see org.apache.wicket.Application#getHomePage()
     */
    @Override
    public Class<? extends Page> getHomePage() {
        return DashboardPage.class;
    }

    /**
     * The method handles the user authentication using the login name and
     * password.
     *
     * @param loginName The login name of the user
     * @param password The password of the user
     * @return Returns the User object or null in case of an Exception.
     */
    public User authenticate(String loginName, String password) {
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginName, password);
        AuthenticationManager am = (AuthenticationManager) applicationContext.getBean("authenticationManager");
        try {
            Authentication authentication = am.authenticate(token);
            return (User) authentication.getPrincipal();
        } catch (AuthenticationException ae) {
            logger.debug("acegi authentication failed: " + ae);
            return null;
        }
    }

    /**
     * This method will try to identify the user by using cookies and tries to
     * auto login the user.
     *
     * @return Returns <code>true</code> on successful identification otherwise <code>false</code>.
     */
    private boolean attemptRememberMeAutoLogin() {
        logger.debug("checking cookies for remember-me auto login");
        Cookie[] cookies = ((WebRequest) RequestCycle.get().getRequest()).getCookies();
        if (cookies == null) {
            logger.debug("no cookies found");
            return false;
        }

        for (Cookie c : cookies) {
            if (logger.isDebugEnabled()) {
                logger.debug("examining cookie: " + WebUtils.getDebugStringForCookie(c));
            }
            if (!c.getName().equals("jtrac")) {
                continue;
            }
            String value = c.getValue();
            logger.debug("found jtrac cookie: " + value);
            if (value == null) {
                continue;
            }
            int index = value.indexOf(':');
            if (index == -1) {
                continue;
            }
            String loginName = value.substring(0, index);
            String encodedPassword = value.substring(index + 1);
            logger.debug("valid cookie, attempting authentication");
            User user = (User) getJtrac().loadUserByUsername(loginName);
            if (encodedPassword.equals(user.getPassword())) {
                JtracSession.get().setUser(user);
                logger.debug("remember me login success");
                return true;
            }
        } // end for
          // no valid cookies were found
        return false;
    }
}