package org.apereo.cas.config;

import com.google.common.base.Throwables;
import net.shibboleth.utilities.java.support.velocity.SLF4JLogChute;
import net.shibboleth.utilities.java.support.xml.BasicParserPool;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.apache.velocity.runtime.resource.loader.FileResourceLoader;
import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.support.saml.OpenSamlConfigBean;
import org.opensaml.core.xml.XMLObjectBuilderFactory;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.io.MarshallerFactory;
import org.opensaml.core.xml.io.UnmarshallerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;
import org.springframework.ui.velocity.VelocityEngineFactoryBean;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * This is {@link CoreSamlConfiguration}.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
@Configuration("coreSamlConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CoreSamlConfiguration {

    /**
     * The constant POOL_SIZE.
     */
    private static final int POOL_SIZE = 100;

    @Autowired
    private CasConfigurationProperties casProperties;

    /**
     * Velocity engine velocity engine factory bean.
     *
     * @return the velocity engine factory bean
     */
    @Lazy
    @Bean(name = "shibboleth.VelocityEngine")
    public VelocityEngineFactoryBean velocityEngineFactoryBean() {
        final VelocityEngineFactoryBean bean = new VelocityEngineFactoryBean();

        final Properties properties = new Properties();
        properties.put("runtime.log.logsystem.class", SLF4JLogChute.class.getName());
        properties.put("input.encoding", "UTF-8");
        properties.put("output.encoding", "UTF-8");
        properties.put("resource.loader", "file, classpath, string");
        properties.put("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        properties.put("string.resource.loader.class", StringResourceLoader.class.getName());
        properties.put("file.resource.loader.class", FileResourceLoader.class.getName());
        properties.put("file.resource.loader.path", FileUtils.getTempDirectory().getAbsolutePath());
        properties.put("file.resource.loader.cache", false);
        bean.setOverrideLogging(false);
        bean.setVelocityProperties(properties);
        return bean;
    }

    /**
     * Open saml config bean open saml config bean.
     *
     * @return the open saml config bean
     */
    @Bean(name = "shibboleth.OpenSAMLConfig")
    public OpenSamlConfigBean openSamlConfigBean() {
        final OpenSamlConfigBean bean = new OpenSamlConfigBean();
        bean.setParserPool(parserPool());
        return bean;
    }

    /**
     * Parser pool basic parser pool.
     *
     * @return the basic parser pool
     */
    @Bean(name = "shibboleth.ParserPool", initMethod = "initialize")
    public BasicParserPool parserPool() {
        final BasicParserPool pool = new BasicParserPool();
        pool.setMaxPoolSize(POOL_SIZE);
        pool.setCoalescing(true);
        pool.setIgnoreComments(true);
        pool.setXincludeAware(false);
        pool.setExpandEntityReferences(false);
        pool.setIgnoreComments(true);
        pool.setNamespaceAware(true);

        final Map<String, Object> attributes = new HashMap<>();
        try {
            final Class clazz = ClassUtils.getClass(casProperties.getSamlCore().getSecurityManager());
            attributes.put("http://apache.org/xml/properties/security-manager", clazz.newInstance());
        } catch (final Exception e) {
            throw Throwables.propagate(e);
        }
        pool.setBuilderAttributes(attributes);

        final Map<String, Boolean> features = new HashMap<>();
        features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE);
        features.put("http://apache.org/xml/features/validation/schema/normalized-value",
                Boolean.FALSE);
        features.put("http://javax.xml.XMLConstants/feature/secure-processing",
                Boolean.TRUE);
        features.put("http://xml.org/sax/features/external-general-entities",
                Boolean.FALSE);
        features.put("http://xml.org/sax/features/external-parameter-entities",
                Boolean.FALSE);
        pool.setBuilderFeatures(features);
        return pool;
    }

    /**
     * Builder factory xml object builder factory.
     *
     * @return the xml object builder factory
     */
    @Bean(name = "shibboleth.BuilderFactory")
    @DependsOn("shibboleth.OpenSAMLConfig")
    public XMLObjectBuilderFactory builderFactory() {
        return XMLObjectProviderRegistrySupport.getBuilderFactory();
    }

    /**
     * Marshaller factory marshaller factory.
     *
     * @return the marshaller factory
     */
    @Bean(name = "shibboleth.MarshallerFactory")
    @DependsOn("shibboleth.OpenSAMLConfig")
    public MarshallerFactory marshallerFactory() {
        return XMLObjectProviderRegistrySupport.getMarshallerFactory();
    }

    /**
     * Unmarshaller factory unmarshaller factory.
     *
     * @return the unmarshaller factory
     */
    @Bean(name = "shibboleth.UnmarshallerFactory")
    @DependsOn("shibboleth.OpenSAMLConfig")
    public UnmarshallerFactory unmarshallerFactory() {
        return XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
    }
}

@@ -282,24 +282,77 @@
 ClassUtils;%0A
+import org.apache.velocity.runtime.RuntimeConstants;%0A
 import org.a
@@ -2231,37 +2231,52 @@
 put(
-%22r
+R
 untime
-.log.logsystem.class%22
+Constants.RUNTIME_LOG_LOGSYSTEM_CLASS
 , SL
@@ -2332,24 +2332,39 @@
 put(
-%22input.encoding%22
+RuntimeConstants.INPUT_ENCODING
 , %22U
@@ -2398,25 +2398,40 @@
 put(
-%22output.encoding%22
+RuntimeConstants.OUTPUT_ENCODING
 , %22U
@@ -2465,52 +2465,327 @@
 put(
-%22resource.loader%22, %22file, classpath, string%22
+RuntimeConstants.ENCODING_DEFAULT, %22UTF-8%22);%0A        properties.put(RuntimeConstants.RESOURCE_LOADER, %22file, classpath, string%22);%0A        properties.put(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, FileUtils.getTempDirectory().getAbsolutePath());%0A        properties.put(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, false
 );%0A 
@@ -3071,170 +3071,8 @@
 ));%0A
-        properties.put(%22file.resource.loader.path%22, FileUtils.getTempDirectory().getAbsolutePath());%0A        properties.put(%22file.resource.loader.cache%22, false);%0A
     

Use velocity constants when configuring engine factory