All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ovea.tajin.framework.app.InternalWebModule.groovy Maven / Gradle / Ivy

There is a newer version: 3.9
Show newest version
/**
 * Copyright (C) 2011 Ovea 
 *
 * 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.ovea.tajin.framework.app

import com.google.inject.Injector
import com.google.inject.Provider
import com.google.inject.matcher.Matchers
import com.google.inject.servlet.RequestScoped
import com.google.inject.servlet.ServletModule
import com.ovea.tajin.framework.i18n.I18NHandler
import com.ovea.tajin.framework.i18n.I18NService
import com.ovea.tajin.framework.i18n.I18NServiceFactory
import com.ovea.tajin.framework.i18n.JsonI18NServiceFactory
import com.ovea.tajin.framework.jmx.JmxModule
import com.ovea.tajin.framework.scheduling.SchedulingModule
import com.ovea.tajin.framework.security.TokenBuilder
import com.ovea.tajin.framework.support.guice.*
import com.ovea.tajin.framework.support.jersey.AuditResourceFilterFactory
import com.ovea.tajin.framework.support.jersey.GzipEncoder
import com.ovea.tajin.framework.support.jersey.PermissionResourceFilterFactory
import com.ovea.tajin.framework.support.jersey.SecurityResourceFilterFactory
import com.ovea.tajin.framework.support.shiro.GuiceShiroFilter
import com.ovea.tajin.framework.support.shiro.MemoryCacheManager
import com.ovea.tajin.framework.support.shiro.SecurityFilter
import com.ovea.tajin.framework.support.shiro.VersionedRememberMeManager
import com.ovea.tajin.framework.template.*
import com.ovea.tajin.framework.util.PropertySettings
import com.ovea.tajin.framework.web.CookieLocaleManager
import com.ovea.tajin.framework.web.RequestLog
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer
import org.apache.shiro.SecurityUtils
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy
import org.apache.shiro.authc.pam.ModularRealmAuthenticator
import org.apache.shiro.authz.ModularRealmAuthorizer
import org.apache.shiro.cache.CacheManager
import org.apache.shiro.codec.Hex
import org.apache.shiro.io.DefaultSerializer
import org.apache.shiro.realm.Realm
import org.apache.shiro.web.mgt.DefaultWebSecurityManager
import org.apache.shiro.web.mgt.WebSecurityManager
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager
import org.eclipse.jetty.servlets.CrossOriginFilter
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import javax.inject.Inject

/**
 * @author Mathieu Carbou ([email protected])
 * @date 2013-04-26
 */
class InternalWebModule extends ServletModule {

    private static final Logger LOGGER = LoggerFactory.getLogger(Tajin)

    private static final int DAY_SEC = 60 * 60 * 24

    private final List applications = new LinkedList<>()
    private final PropertySettings settings

    InternalWebModule(PropertySettings settings, Collection applications) {
        this.applications.addAll(applications)
        this.settings = settings
    }

    @Override
    protected void configureServlets() {
        bind(PropertySettings).toInstance(settings)
        bind(Locale).toProvider(CookieLocaleManager).in(RequestScoped)

        // bind TokenBuilder if needed
        settings.getString('token.key', null)?.with { String key ->
            LOGGER.info(" + TokenBuilder support")
            bind(TokenBuilder).toProvider(new Provider() {
                TokenBuilder get() { new TokenBuilder(Hex.decode(key)) }
            }).in(javax.inject.Singleton)
        }

        // bind schedueler if needed
        if (settings.getBoolean('scheduling.enabled', false)) {
            LOGGER.info(" + JobScheduler support")
            install(new SchedulingModule())
        }

        if (settings.getBoolean('jmx.enabled', true)) {
            LOGGER.info(" + JMX support")
            install(new JmxModule())
        }

        // setup groovy templating system
        LOGGER.info(" + @Template support")
        bind(TemplateCompiler).toProvider(new Provider() {
            @Override
            TemplateCompiler get() {
                TemplateCompiler compiler = new GroovyTemplateCompiler()
                if (settings.getBoolean('template.cache', true)) {
                    compiler = new CachingTemplateCompiler(compiler)
                }
                return compiler
            }
        }).in(javax.inject.Singleton)
        bind(TemplateResolver).toProvider(new Provider() {
            @Inject TemplateCompiler compiler

            @Override
            TemplateResolver get() {
                TemplateResolver resolver = new ResourceTemplateResolver(compiler)
                if (settings.getBoolean('template.cache', true)) {
                    resolver = new CachingTemplateResolver(resolver)
                }
                return resolver
            }
        }).in(javax.inject.Singleton)
        binder().bindListener(Matchers.any(), new TmplHandler());

        // setup i18n
        LOGGER.info(" + @Bundle support (i18n)")
        bind(I18NServiceFactory).toProvider(new Provider() {
            @Override
            I18NServiceFactory get() {
                JsonI18NServiceFactory factory = new JsonI18NServiceFactory()
                factory.debug = !settings.getBoolean('i18n.cache', true)
                factory.missingKeyBehaviour = settings.getEnum(I18NService.MissingKeyBehaviour, 'i18n.miss', I18NService.MissingKeyBehaviour.RETURN_KEY)
                return factory
            }
        }).in(javax.inject.Singleton)
        binder().bindListener(Matchers.any(), new I18NHandler());

        // bind filters
        bind(GuiceContainer).in(javax.inject.Singleton)
        bind(CrossOriginFilter).in(javax.inject.Singleton)

        // support method expanders
        TajinGuice.in(binder()).handleMethodAfterInjection(Expand, ExpandHandler)

        // configure CORS filter if desired
        settings.getString('cors.allowedOrigins', null)?.with { String origin ->
            LOGGER.info(" + CORS support")
            filter('/*').through(CrossOriginFilter, [
                allowedMethods: 'GET,POST,HEAD,PUT,DELETE',
                allowedOrigins: origin
            ])
        }

        // important filter to manage HTTP contextual scopes
        filter('/*').through(HttpContextFilter)

        // setup security layer if required
        boolean secured = settings.getBoolean('security.enabled', false)
        if (secured) {
            LOGGER.info(" + Securtity support")
            bind(org.apache.shiro.mgt.SecurityManager).to(WebSecurityManager)
            bind(WebSecurityManager).toProvider(new Provider() {
                @Inject Injector injector

                @Override
                WebSecurityManager get() {
                    List realms = settings.getStrings('security.realms').collect { it.empty ? null : injector.getInstance(Thread.currentThread().contextClassLoader.loadClass(it)) as Realm }
                    DefaultWebSecurityManager manager = new DefaultWebSecurityManager(
                        // WARNNG: order of setters is important
                        sessionManager: new ServletContainerSessionManager(),
                        rememberMeManager: !settings.has("rememberme.cookie.name") ? null : new VersionedRememberMeManager(
                            version: settings.getInt('rememberme.cookie.version', 1),
                            serializer: new DefaultSerializer<>(),
                            cipherKey: Hex.decode(settings.getString('rememberme.cookie.key')),
                            cookie: new com.ovea.tajin.framework.web.HttpCookie(
                                name: settings.getString("rememberme.cookie.name"),
                                httpOnly: true,
                                maxAge: settings.getInt("rememberme.cookie.days", 365) * DAY_SEC
                            )
                        ),
                        authenticator: new ModularRealmAuthenticator(
                            authenticationStrategy: new FirstSuccessfulStrategy(),
                        ),
                        authorizer: new ModularRealmAuthorizer(),
                        realms: realms,
                        cacheManager: settings.getString('security.cache', MemoryCacheManager.name).with { it.trim().length() == 0 ? null : injector.getInstance(Thread.currentThread().contextClassLoader.loadClass(it)) as CacheManager },
                    )
                    SecurityUtils.securityManager = manager
                    return manager
                }
            }).in(javax.inject.Singleton)
            filter('/*').through(GuiceShiroFilter)
            filter('/*').through(SecurityFilter)
        }

        // setup performance logger
        if (settings.getBoolean('logging.perf', false)) {
            LOGGER.info(" + Performance logging support")
            filter('/*').through(RequestLog, [
                secured: secured as String
            ])
        }

        // setup REST API
        bind(RootPath)
        if (secured) {
            serve("/*").with(GuiceContainer, [
                "com.sun.jersey.spi.container.ContainerResponseFilters": GzipEncoder.name,
                "com.sun.jersey.spi.container.ResourceFilters": "${AuditResourceFilterFactory.name};${SecurityResourceFilterFactory.name};${PermissionResourceFilterFactory.name}" as String
            ])
        } else {
            serve("/*").with(GuiceContainer, [
                "com.sun.jersey.spi.container.ContainerResponseFilters": GzipEncoder.name,
                "com.sun.jersey.spi.container.ResourceFilters": "${AuditResourceFilterFactory.name}" as String
            ])
        }

        // configure discovered applications
        WebBinder webBinder = new WebBinder(binder())
        applications.each {
            LOGGER.info("Configuring application: ${it.class.simpleName}")
            it.onInit(webBinder, settings)
            bind(it.class).toInstance(it)
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy