uk.q3c.krail.core.guice.DefaultBindingManager.java Source code

Java tutorial

Introduction

Here is the source code for uk.q3c.krail.core.guice.DefaultBindingManager.java

Source

/*
 *
 *  * Copyright (c) 2016. David Sowerby
 *  *
 *  * 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 uk.q3c.krail.core.guice;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
import com.google.inject.util.Modules;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.bval.guice.ValidationModule;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.q3c.krail.core.config.ApplicationConfigurationModule;
import uk.q3c.krail.core.data.DataModule;
import uk.q3c.krail.core.eventbus.EventBusModule;
import uk.q3c.krail.core.guice.threadscope.ThreadScopeModule;
import uk.q3c.krail.core.guice.uiscope.UIScopeModule;
import uk.q3c.krail.core.guice.vsscope.VaadinSessionScopeModule;
import uk.q3c.krail.core.i18n.I18NModule;
import uk.q3c.krail.core.navigate.NavigationModule;
import uk.q3c.krail.core.navigate.sitemap.MasterSitemap;
import uk.q3c.krail.core.navigate.sitemap.SitemapModule;
import uk.q3c.krail.core.navigate.sitemap.StandardPagesModule;
import uk.q3c.krail.core.option.InMemory;
import uk.q3c.krail.core.option.OptionModule;
import uk.q3c.krail.core.persist.inmemory.common.InMemoryModule;
import uk.q3c.krail.core.push.PushModule;
import uk.q3c.krail.core.services.ServicesModel;
import uk.q3c.krail.core.services.ServicesModule;
import uk.q3c.krail.core.shiro.DefaultShiroModule;
import uk.q3c.krail.core.shiro.ShiroVaadinModule;
import uk.q3c.krail.core.shiro.aop.KrailShiroAopModule;
import uk.q3c.krail.core.ui.DataTypeModule;
import uk.q3c.krail.core.ui.DefaultUIModule;
import uk.q3c.krail.core.user.UserModule;
import uk.q3c.krail.core.validation.KrailValidationModule;
import uk.q3c.krail.core.view.ViewModule;
import uk.q3c.krail.core.view.component.DefaultComponentModule;
import uk.q3c.krail.util.UtilsModule;

import javax.servlet.ServletContextEvent;
import java.util.ArrayList;
import java.util.List;

/**
 * Collects together all the modules used for bindings, and passes them to the {@link Injector}  during the injector creation process.  The separation into
 * different groupings of modules is for clarity only - they do not have to be separate for any other reason.
 */
public abstract class DefaultBindingManager extends GuiceServletContextListener {
    //Visible for testing
    static Injector injector;
    private static Logger log = LoggerFactory.getLogger(DefaultBindingManager.class);

    protected DefaultBindingManager() {
        super();
    }

    public static Injector injector() {
        return injector;
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        log.info("Stopping services");
        try {
            if (injector != null) {
                injector.getInstance(ServicesModel.class).stopAllServices();
            } else {
                log.debug("Injector has not been constructed, no call made to stop services");
            }
        } catch (Exception e) {
            log.error("Exception while stopping services", e);
        }
        //context may not have been crated, and super does not check for it
        if (servletContextEvent.getServletContext() != null) {
            super.contextDestroyed(servletContextEvent);
        }
    }

    /**
     * Module instances for the core should be added in {@link #getModules()}. Module instances for the app using Krail
     * should be added to {@link #addAppModules(List)}
     *
     * @see com.google.inject.servlet.GuiceServletContextListener#getInjector()
     */
    @Override
    public Injector getInjector() {
        if (injector == null) {
            createInjector();
        }
        return injector;
    }

    protected void createInjector() {
        injector = Guice.createInjector(getModules());
        log.debug("injector created");

        // By default Shiro provides a binding to DefaultSecurityManager, but that is replaced by a binding to
        // KrailSecurityManager in {@link DefaultShiroModule#bindSecurityManager} (or potentially to another security manager if
        // the developer overrides that method)
        SecurityManager securityManager = injector.getInstance(SecurityManager.class);
        SecurityUtils.setSecurityManager(securityManager);

    }

    private List<Module> getModules() {
        List<Module> coreModules = new ArrayList<>(30);

        coreModules.add(uiModule());
        coreModules.add(i18NModule());
        coreModules.add(applicationConfigurationModule());
        coreModules.add(new SitemapModule());

        coreModules.add(new ThreadScopeModule());
        coreModules.add(new UIScopeModule());
        coreModules.add(new VaadinSessionScopeModule());

        coreModules.add(new ServicesModule());

        coreModules.add(shiroModule());
        coreModules.add(shiroVaadinModule());
        coreModules.add(shiroAopModule());

        coreModules.add(servletModule());

        coreModules.add(standardPagesModule());

        coreModules.add(viewModule());

        coreModules.add(componentModule());

        coreModules.add(userModule());

        coreModules.add(optionModule());

        coreModules.add(eventBusModule());

        coreModules.add(navigationModule());

        coreModules.add(dataModule());
        coreModules.add(dataTypeModule());
        coreModules.add(pushModule());

        addUtilModules(coreModules);
        addValidationModules(coreModules);

        addAppModules(coreModules);
        addSitemapModules(coreModules);
        addPersistenceModules(coreModules);
        return coreModules;
    }

    protected void addUtilModules(List<Module> coreModules) {
        coreModules.add(new UtilsModule());
    }

    protected Module shiroAopModule() {
        return new KrailShiroAopModule();
    }

    /**
     * Override this if you have provided your own {@link DataTypeModule} implementation
     *
     * @return a new {@link DataTypeModule} instance
     */
    protected Module dataTypeModule() {
        return new DataTypeModule();
    }

    /**
     * Override this if you have provided your own {@link PushModule} implementation
     *
     * @return a new {@link PushModule} instance
     */
    protected Module pushModule() {
        return new PushModule();
    }

    protected Module uiModule() {
        return new DefaultUIModule();
    }

    /**
     * Override this if you have provided your own {@link DataModule} implementation
     *
     * @return a new {@link DataModule} instance
     */
    protected Module dataModule() {
        return new DataModule();
    }

    /**
     * Override this if you have provided your own {@link EventBusModule} implementation
     *
     * @return a new {@link EventBusModule} instance
     */
    protected Module eventBusModule() {
        return new EventBusModule();
    }

    /**
     * Override this if you have provided your own {@link NavigationModule}
     *
     * @return new instance of ApplicationConfigurationModule
     */

    protected AbstractModule navigationModule() {
        return new NavigationModule();
    }

    /**
     * Override this method if you want to use an alternative implementation for the Krail validation integration.  You
     * will need to keep the Apache Bval {{@link ValidationModule} unless you replace the the javax validation
     * implementation.
     *
     * @param modules
     *         the list used to collect modules for injector creation
     */
    protected void addValidationModules(List<Module> modules) {

        final Module validationModule = Modules.override(new ValidationModule()).with(new KrailValidationModule());
        modules.add(validationModule);
    }

    /**
     * Sets the default active source to read/write Option values from / to the in memory store
     *
     * Override this if you have provided your own {@link OptionModule} or want to change the active source
     *
     * @return module instance
     */
    protected Module optionModule() {
        return new OptionModule().activeSource(InMemory.class);
    }

    /**
     * Override this if you have provided your own {@link I18NModule}
     *
     * @return a Module fr I18N
     */
    protected Module i18NModule() {
        return new I18NModule();
    }

    /**
     * Override this if you have provided your own {@link ApplicationConfigurationModule}
     *
     * @return new instance of ApplicationConfigurationModule
     */

    protected Module applicationConfigurationModule() {
        return new ApplicationConfigurationModule();
    }

    /**
     * Modules used in the creation of the {@link MasterSitemap} do not actually need to be separated, this just makes a convenient way of seeing them as a
     * group
     *
     * @param modules
     *         the list used to collect modules for injector creation
     */
    @SuppressFBWarnings("ACEM_ABSTRACT_CLASS_EMPTY_METHODS")
    protected void addSitemapModules(List<Module> modules) {
    }

    protected Module componentModule() {
        return new DefaultComponentModule();
    }

    /**
     * Override this if you have provided your own {@link ServletModule}
     *
     * @return servlet module instance
     */
    protected Module servletModule() {
        return new BaseServletModule();
    }

    /**
     * Override this method if you have sub-classed {@link ShiroVaadinModule} to provide your own bindings for Shiro
     * related exceptions.
     *
     * @return a module for bindings which realte to Shiro wihtin a Vaadin environment
     */
    protected Module shiroVaadinModule() {
        return new ShiroVaadinModule();
    }

    /**
     * Override this if you have sub-classed {@link StandardPagesModule} to provide bindings to your own standard page
     * views
     */
    protected Module standardPagesModule() {
        return new StandardPagesModule();
    }

    /**
     * Override this if you have sub-classed {@link ViewModule} to provide bindings to your own standard page views
     */
    protected Module viewModule() {
        return new ViewModule();
    }

    /**
     * Override this method if you have sub-classed {@link DefaultShiroModule} to provide bindings to your Shiro
     * related implementations (for example, {@link Realm} and {@link CredentialsMatcher}
     *
     * @return a new {@link DefaultShiroModule} instance
     */

    protected Module shiroModule() {
        return new DefaultShiroModule();
    }

    /**
     * Override this if you have sub-classed {@link UserModule} to provide bindings to your user related
     * implementations
     *
     * @return a new instance of {@link UserModule} or sub-class
     */
    protected UserModule userModule() {
        return new UserModule();
    }

    /**
     * Add as many application specific Guice modules as you wish by overriding this method.
     *
     * @param modules
     *         the list used to collect modules for injector creation
     */
    protected abstract void addAppModules(List<Module> modules);

    /**
     * Add as many persistence related modules as needed.  These modules do not need to be separated, this just forms a convneient grouping for clarity
     *
     * @param modules
     *         the list used to collect modules for injector creation
     */
    protected void addPersistenceModules(List<Module> modules) {
        modules.add(new InMemoryModule().provideOptionDao().providePatternDao());
    }
}