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

org.rythmengine.spring.web.RythmConfigurer Maven / Gradle / Ivy

package org.rythmengine.spring.web;

import org.rythmengine.RythmEngine;
import org.rythmengine.conf.RythmConfigurationKey;
import org.rythmengine.exception.RythmException;
import org.rythmengine.extension.ISourceCodeEnhancer;
import org.rythmengine.spring.RythmEngineFactory;
import org.rythmengine.template.ITemplate;
import org.rythmengine.utils.S;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: luog
 * Date: 2/12/13
 * Time: 7:58 PM
 * To change this template use File | Settings | File Templates.
 */
@Configuration
@EnableWebMvc
@ComponentScan("org.rythmengine.spring.web")
public class RythmConfigurer extends RythmEngineFactory implements
    RythmHolder, InitializingBean, DisposableBean,
    ResourceLoaderAware, ServletContextAware,
    WebMvcConfigurer {

    /**
     * so that app developer can retrieve the servlet context with
     * {@code @servletContext}
     */
    public static final String CTX_SERVLET_CONTEXT = "servletContext";

    //public static final String CTX_

    public static final String CONF_USER_CONTEXT = "userContext";
    /**
     * Do we allow add all http request parameters into the render args?
     */
    public static final String CONF_OUTOUT_REQ_PARAMS = "outputRequestParameters";

    public static final String CONF_UNDERSCORE_IMPLICIT_VAR_NAME = "underscoreImplicityVarName";

    public static final String CONF_ENABLE_SESSION_MANAGER = "enableSessionManager";

    public static final String CONF_ENABLE_USER_AGENT_DETECTOR = "enableUserAgentDetector";

    public static final String CONF_CSRF_PARAM_NAME = "csrfParameterName";

    public static final String CONF_CSRF_HEADER_NAME = "csrfHeaderName";

    private static RythmEngine engine;

    private ServletContext ctx;

    private boolean outputRequestParameters = false;

    private boolean underscoreImplicitVariableName = false;

    private String sessionCookiePrefix = null;

    private String sessionCookieExpire = null;

    private boolean autoCsrfCheck = true;

    private boolean enableSessionManager = false;

    private boolean enableUserAgentDetector = false;

    private boolean enableCacheFor = false;

    private static String secretKey = null;

    private static SecretKeySensor secretKeySensor;

    private String csrfParamName = null;

    private String csrfHeaderName = null;

    private String autoImports = null;

    private static RythmConfigurer inst;

    public static RythmConfigurer getInstance() {
        return inst;
    }

    public void setRythmEngine(RythmEngine engine) {
        this.engine = engine;
    }

    @Override
    public RythmEngine getRythmEngine() {
        return engine;
    }

    public static RythmEngine engine() {
        return engine;
    }

    public void setOutputRequestParameters(boolean outputRequestParameters) {
        this.outputRequestParameters = outputRequestParameters;
    }

    public void setUnderscoreImplicitVariableName(boolean underscoreImplicitVariableName) {
        this.underscoreImplicitVariableName = underscoreImplicitVariableName;
    }

    public void setAutoCsrfCheck(boolean autoCsrfCheck) {
        this.autoCsrfCheck = autoCsrfCheck;
    }

    public void setAutoImports(String autoImports) {this.autoImports = autoImports;}

    public void setEnableCacheFor(boolean enableCacheFor) {
        this.enableCacheFor = enableCacheFor;
    }

    public void setEnableSessionManager(boolean enableSessionManager) {
        this.enableSessionManager = enableSessionManager;
    }

    public void setEnableUserAgentDetector(boolean enableUserAgentDetector) {
        this.enableUserAgentDetector = enableUserAgentDetector;
    }

    public boolean sessionManagerEnabled() {
        return enableSessionManager;
    }

    public void setSecretKeySensor(String secretKeySensor) throws Exception {
        Class c = (Class)Class.forName(secretKeySensor);
        this.secretKeySensor = c.newInstance();
    }

    private SecretKeySensor getSecretKeySensor() {
        if (null == secretKeySensor) {
            secretKeySensor = new SecretKeySensor.DefaultSecretKeySensor(getApplicationContext());
        }
        return secretKeySensor;
    }

    public void setSecretKey(String secretKey) {
        Assert.hasText(secretKey);
        int len = secretKey.length();
        int delta = 16 - len;
        if (delta > 0) {
            StringBuilder sb = new StringBuilder(secretKey);
            for (int i = 0; i < delta; ++i) {
                sb.append("\u0000");
            }
            secretKey = sb.toString();
        }
        RythmConfigurer.secretKey = secretKey;
    }

    public static String getSecretKey() {
        return secretKey;
    }

    public void setSessionCookiePrefix(String sessionCookiePrefix) {
        Assert.notNull(sessionCookiePrefix);
        this.sessionCookiePrefix = sessionCookiePrefix;
    }

    public void setConfSessionCookieExpire(String sessionCookieExpire) {
        Assert.notNull(sessionCookieExpire);
        this.sessionCookieExpire = sessionCookieExpire;
    }

    public void setCsrfParamName(String csrfParamName) {
        Assert.notNull(csrfParamName);
        this.csrfParamName = csrfParamName;
    }

    public void setCsrfHeaderName(String csrfHeaderName) {
        Assert.notNull(csrfHeaderName);
        this.csrfHeaderName = csrfHeaderName;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (null == engine) {
            engine = createRythmEngine();
        }
        inst = this;
        if (null == secretKey) {
            secretKey = getSecretKeySensor().getSecretKey();
        }
    }

    @Override
    public void destroy() throws Exception {
        if (null != engine) {
            engine.shutdown();
        }
    }

    private Map userContext = new HashMap();

    private void setUserContext(String key, Object v) {
        userContext.put(key, v);
    }

    @Override
    protected void configRythm(Map config) {
        WebApplicationContext ctx = (WebApplicationContext)getApplicationContext();
        boolean allowFileWrite = true;
        Object o = config.get(RythmConfigurationKey.ENGINE_FILE_WRITE_ENABLED.getKey());
        if (null != o) {
            allowFileWrite = Boolean.parseBoolean(String.valueOf(o));
        }
        if (allowFileWrite && !config.containsKey(RythmConfigurationKey.HOME_TMP.getKey())) {
            File tmpdir = (File)ctx.getServletContext().getAttribute("javax.servlet.context.tempdir");
            if (null != tmpdir) {
                tmpdir = new File(tmpdir, "__rythm");
                if (!tmpdir.exists()) {
                    tmpdir.mkdirs();
                }
                config.put(RythmConfigurationKey.HOME_TMP.getKey(), tmpdir);
            }
        }

        config.put(RythmConfigurationKey.CODEGEN_SOURCE_CODE_ENHANCER.getKey(), new ISourceCodeEnhancer() {
            ImplicitVariables implicitVariables = new ImplicitVariables(underscoreImplicitVariableName);

            @Override
            public List imports() {
                List l = new ArrayList();
                if (null != autoImports) {
                    return Arrays.asList(autoImports.split("[, ;:]+"));
                }
                return l;
            }

            @Override
            public String sourceCode() {
                return "protected org.rythmengine.utils.RawData url(String path) {\n" +
                        "if (path == null) path = \"/\";\n" +
                        "if (!path.startsWith(\"//\") && !path.startsWith(\"http\")) {\n" +
                        "\tpath = __request.getContextPath() + (path.startsWith(\"/\") ? \"\" : \"/\") + path; \n" +
                        "}\n" +
                        "return new org.rythmengine.utils.RawData(path);\n" +
                        "}\n\n" +
                        "protected org.rythmengine.utils.RawData fullUrl(String path) {\n" +
                        "if (path == null) path = \"/\";\n" +
                        "if (path.startsWith(\"//\") || path.startsWith(\"http\")) {\n" +
                        "\treturn new org.rythmengine.utils.RawData(path);\n" +
                        "}\n" +
                        "if (!path.startsWith(\"/\")) {path = path + \"/\";}\n" +
                        "String ctx = __request.getContextPath(); StringBuilder sb = new StringBuilder();\n" +
                        "sb.append(__request.getScheme());\n" +
                        "sb.append(\"://\");\n" +
                        "sb.append(__request.getServerName()).append(\":\");\n" +
                        "sb.append(__request.getServerPort()); \n" +
                        "sb.append(ctx).append(path);\n" +
                        "return new org.rythmengine.utils.RawData(sb);" +
                        "}\n"
                        ;
            }

            @Override
            public Map getRenderArgDescriptions() {
                Map m = new HashMap();
                for (ImplicitVariables.Var var : implicitVariables.vars) {
                    m.put(var.name(), var.type);
                }
                return m;
            }

            @Override
            public void setRenderArgs(ITemplate template) {
                // already set in RythmView
//                Map m = new HashMap();
//                for (ImplicitVariables.Var var : implicitVariables.vars) {
//                    m.put(var.name(), var.evaluate());
//                }
//                template.__setRenderArgs(m);
            }
        });
    }

    @Override
    protected void postProcessRythmEngine(RythmEngine engine) throws IOException, RythmException {
        engine.setProperty(CONF_USER_CONTEXT, userContext);
        setUserContext(CTX_SERVLET_CONTEXT, ctx);
        setUserContext(ServletContext.class.getName(), ctx);
        engine.setProperty(CONF_OUTOUT_REQ_PARAMS, outputRequestParameters);
        engine.setProperty(CONF_UNDERSCORE_IMPLICIT_VAR_NAME, underscoreImplicitVariableName);
        engine.setProperty(CONF_ENABLE_SESSION_MANAGER, enableSessionManager);
        engine.setProperty(CONF_ENABLE_USER_AGENT_DETECTOR, enableUserAgentDetector);
        if (null != csrfHeaderName) engine.setProperty(CONF_CSRF_HEADER_NAME, csrfHeaderName);
        if (null != csrfParamName) engine.setProperty(CONF_CSRF_PARAM_NAME, csrfParamName);
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        ctx = servletContext;
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {

    }

    @Override
    public void configureMessageConverters(List> converters) {

    }

    @Override
    public Validator getValidator() {
        return null;
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {

    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {

    }

    @Override
    public void addArgumentResolvers(List argumentResolvers) {

    }

    @Override
    public void addReturnValueHandlers(List returnValueHandlers) {

    }

    @Override
    public void configureHandlerExceptionResolvers(List exceptionResolvers) {

    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        if (enableSessionManager) {
            if (S.empty(secretKey)) {
                throw new RuntimeException("No secure salt configured while session manager is enabled");
            }
            SessionManager sm = new SessionManager();
            sm.setSessionExpire(sessionCookieExpire);
            sm.setSessionPrefix(sessionCookiePrefix);
            registry.addInterceptor(sm);
        }
        if (autoCsrfCheck) {
            CsrfManager csrfManager = new CsrfManager();
            csrfManager.setParameterName(csrfParamName);
            csrfManager.setHeaderName(csrfHeaderName);
            registry.addInterceptor(csrfManager);
        }
        if (enableCacheFor && enableCache) {
            CacheInterceptor ci = new CacheInterceptor();
            ci.setEngine(engine);
            registry.addInterceptor(ci);
        }
        if (enableUserAgentDetector) {
            UADetector ua = new UADetector();
            registry.addInterceptor(ua);
        }
    }

    @Override
    public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy