com.github.peholmst.springsecuritydemo.ui.SpringSecurityDemoApp.java Source code

Java tutorial

Introduction

Here is the source code for com.github.peholmst.springsecuritydemo.ui.SpringSecurityDemoApp.java

Source

/*
 * Copyright (c) 2010 The original author(s)
 *
 * 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 com.github.peholmst.springsecuritydemo.ui;

import java.util.Locale;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import com.github.peholmst.springsecuritydemo.VersionInfo;
import com.github.peholmst.springsecuritydemo.services.CategoryService;
import com.vaadin.Application;
import com.vaadin.service.ApplicationContext.TransactionListener;
import com.vaadin.ui.Window;
import com.vaadin.ui.Component.Event;

/**
 * Main Vaadin application class for this demo. When first initialized, the
 * application displays an instance of {@link LoginView} as its main window.
 * Once a user has logged in successfully, the main window is replaced with an
 * instance of {@link MainView}, which remains the main window until the
 * application is closed.
 * <p>
 * This application class has been annotated with Spring application context
 * annotations. Its scope has been set to "prototype", meaning that a new
 * instance of the class will be returned every time the bean is accessed in the
 * Spring application context.
 * <p>
 * This class contains a lot of logging entries, the purpose of which is to make
 * it possible to follow what happens under the hood at different stages of the
 * application lifecycle.
 * 
 * @author Petter Holmstrm
 */
@Component("applicationBean")
@Scope("prototype")
public class SpringSecurityDemoApp extends Application implements I18nProvider, TransactionListener {

    private static final long serialVersionUID = -1412284137848857188L;

    /**
     * Apache Commons logger for logging stuff.
     */
    protected final Log logger = LogFactory.getLog(getClass());

    @Resource
    private MessageSource messages;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private CategoryService categoryService;

    private LoginView loginView;

    private MainView mainView;

    private static final Locale[] SUPPORTED_LOCALES = { Locale.US, new Locale("fi", "FI"), new Locale("sv", "SE") };

    private static final String[] LOCALE_NAMES = { "English", "Suomi", "Svenska" };

    @Override
    public Locale getLocale() {
        /*
         * Fetch the locale resolved by Spring in the application servlet
         */
        return LocaleContextHolder.getLocale();
    }

    @Override
    public void setLocale(Locale locale) {
        LocaleContextHolder.setLocale(locale);
    }

    @SuppressWarnings("serial")
    @Override
    public void init() {
        if (logger.isDebugEnabled()) {
            logger.debug("Initializing application [" + this + "]");
        }
        // Register listener
        getContext().addTransactionListener(this);

        // Create the views
        loginView = new LoginView(this, authenticationManager);
        loginView.setSizeFull();

        setTheme("SpringSecurityDemo"); // We use a custom theme

        final Window loginWindow = new Window(getMessage("app.title", getVersion()), loginView);
        setMainWindow(loginWindow);

        loginView.addListener(new com.vaadin.ui.Component.Listener() {
            @Override
            public void componentEvent(Event event) {
                if (event instanceof LoginView.LoginEvent) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("User logged on [" + ((LoginView.LoginEvent) event).getAuthentication() + "]");
                    }
                    /*
                     * A user has logged on, which means we can ditch the login
                     * view and open the main view instead. We also have to
                     * update the security context holder.
                     */
                    setUser(((LoginView.LoginEvent) event).getAuthentication());
                    SecurityContextHolder.getContext()
                            .setAuthentication(((LoginView.LoginEvent) event).getAuthentication());
                    removeWindow(loginWindow);
                    loginView = null;
                    mainView = new MainView(SpringSecurityDemoApp.this, categoryService);
                    mainView.setSizeFull();
                    setMainWindow(new Window(getMessage("app.title", getVersion()), mainView));
                }
            }
        });
    }

    @Override
    @PreDestroy
    // In case the application is destroyed by the container
    public void close() {
        if (logger.isDebugEnabled()) {
            logger.debug("Closing application [" + this + "]");
        }
        // Clear the authentication property to log the user out
        setUser(null);
        // Also clear the security context
        SecurityContextHolder.clearContext();
        getContext().removeTransactionListener(this);
        super.close();
    }

    @Override
    protected void finalize() throws Throwable {
        if (logger.isDebugEnabled()) {
            /*
             * This is included to make sure that closed applications get
             * properly garbage collected.
             */
            logger.debug("Garbage collecting application [" + this + "]");
        }
        super.finalize();
    }

    @Override
    public void transactionEnd(Application application, Object transactionData) {
        if (logger.isDebugEnabled()) {
            logger.debug("Transaction ended, removing authentication data from security context");
        }
        /*
         * The purpose of this
         */
        SecurityContextHolder.getContext().setAuthentication(null);
    }

    @Override
    public void transactionStart(Application application, Object transactionData) {
        if (logger.isDebugEnabled()) {
            logger.debug("Transaction started, setting authentication data of security context to ["
                    + application.getUser() + "]");
        }
        /*
         * The security context holder uses the thread local pattern to store
         * its authentication credentials. As requests may be handled by
         * different threads, we have to update the security context holder in
         * the beginning of each transaction.
         */
        SecurityContextHolder.getContext().setAuthentication((Authentication) application.getUser());
    }

    /**
     * Gets the currently logged in user. If this value is <code>null</code>, no
     * user has been logged in yet.
     * 
     * @return an {@link Authentication} instance.
     */
    @Override
    public Authentication getUser() {
        return (Authentication) super.getUser();
    }

    @Override
    public String getVersion() {
        return VersionInfo.getApplicationVersion();
    }

    @Override
    public String getMessage(String code, Object... args) throws NoSuchMessageException {
        return messages.getMessage(code, args, getLocale());
    }

    @Override
    public Locale[] getSupportedLocales() {
        return SUPPORTED_LOCALES;
    }

    @Override
    public String getLocaleDisplayName(Locale locale) {
        for (int i = 0; i < SUPPORTED_LOCALES.length; i++) {
            if (locale.equals(SUPPORTED_LOCALES[i])) {
                return LOCALE_NAMES[i];
            }
        }
        return "Unsupported Locale";
    }
}