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

org.thymeleaf.ConfigurationPrinterHelper Maven / Gradle / Ivy

Go to download

Modern server-side Java template engine for both web and standalone environments

There is a newer version: 3.1.3.RELEASE
Show newest version
/*
 * =============================================================================
 * 
 *   Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org)
 * 
 *   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 org.thymeleaf;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thymeleaf.cache.ICacheManager;
import org.thymeleaf.dialect.IDialect;
import org.thymeleaf.dialect.IExecutionAttributeDialect;
import org.thymeleaf.dialect.IExpressionObjectDialect;
import org.thymeleaf.dialect.IPostProcessorDialect;
import org.thymeleaf.dialect.IPreProcessorDialect;
import org.thymeleaf.dialect.IProcessorDialect;
import org.thymeleaf.expression.IExpressionObjectFactory;
import org.thymeleaf.linkbuilder.ILinkBuilder;
import org.thymeleaf.messageresolver.IMessageResolver;
import org.thymeleaf.postprocessor.IPostProcessor;
import org.thymeleaf.preprocessor.IPreProcessor;
import org.thymeleaf.processor.IProcessor;
import org.thymeleaf.processor.cdatasection.ICDATASectionProcessor;
import org.thymeleaf.processor.comment.ICommentProcessor;
import org.thymeleaf.processor.doctype.IDocTypeProcessor;
import org.thymeleaf.processor.element.IElementModelProcessor;
import org.thymeleaf.processor.element.IElementTagProcessor;
import org.thymeleaf.processor.element.MatchingAttributeName;
import org.thymeleaf.processor.element.MatchingElementName;
import org.thymeleaf.processor.processinginstruction.IProcessingInstructionProcessor;
import org.thymeleaf.processor.text.ITextProcessor;
import org.thymeleaf.processor.xmldeclaration.IXMLDeclarationProcessor;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.util.ProcessorComparators;
import org.thymeleaf.util.StringUtils;

/**
 * 
 * @author Daniel Fernández
 * 
 * @since 1.0
 *
 */
final class ConfigurationPrinterHelper {

    public static final String CONFIGURATION_LOGGER_NAME = org.thymeleaf.TemplateEngine.class.getName() + ".CONFIG";

    private static final Logger configLogger = LoggerFactory.getLogger(CONFIGURATION_LOGGER_NAME);

    
    
    
    
    
    
    static void printConfiguration(final IEngineConfiguration configuration) {

        final ConfigLogBuilder logBuilder = new ConfigLogBuilder();

        final ICacheManager cacheManager = configuration.getCacheManager();
        final Set templateResolvers = configuration.getTemplateResolvers();
        final Set messageResolvers = configuration.getMessageResolvers();
        final Set linkBuilders = configuration.getLinkBuilders();

        logBuilder.line("Initializing Thymeleaf Template engine configuration...");
        logBuilder.line("[THYMELEAF] TEMPLATE ENGINE CONFIGURATION:");
        if (!StringUtils.isEmptyOrWhitespace(Thymeleaf.VERSION)) {
            if (!StringUtils.isEmptyOrWhitespace(Thymeleaf.BUILD_TIMESTAMP)) {
                logBuilder.line("[THYMELEAF] * Thymeleaf version: {} (built {})", Thymeleaf.VERSION, Thymeleaf.BUILD_TIMESTAMP);
            } else {
                logBuilder.line("[THYMELEAF] * Thymeleaf version: {}", Thymeleaf.VERSION);
            }
        }
        logBuilder.line("[THYMELEAF] * Cache Manager implementation: {}", (cacheManager == null? "[no caches]" : cacheManager.getClass().getName()));
        logBuilder.line("[THYMELEAF] * Template resolvers:");
        for (final ITemplateResolver templateResolver : templateResolvers) {
            if (templateResolver.getOrder() != null) {
                logBuilder.line("[THYMELEAF]     * [{}] {}", templateResolver.getOrder(), templateResolver.getName());
            } else{
                logBuilder.line("[THYMELEAF]     * {}", templateResolver.getName());
            }
        }
        logBuilder.line("[THYMELEAF] * Message resolvers:");
        for (final IMessageResolver messageResolver : messageResolvers) {
            if (messageResolver.getOrder() != null) {
                logBuilder.line("[THYMELEAF]     * [{}] {}", messageResolver.getOrder(), messageResolver.getName());
            } else{
                logBuilder.line("[THYMELEAF]     * {}", messageResolver.getName());
            }
        }
        logBuilder.line("[THYMELEAF] * Link builders:");
        for (final ILinkBuilder linkBuilder : linkBuilders) {
            if (linkBuilder.getOrder() != null) {
                logBuilder.line("[THYMELEAF]     * [{}] {}", linkBuilder.getOrder(), linkBuilder.getName());
            } else{
                logBuilder.line("[THYMELEAF]     * {}", linkBuilder.getName());
            }
        }

        final Set dialectConfigurations = configuration.getDialectConfigurations();

        int dialectIndex = 1;
        final Integer totalDialects = Integer.valueOf(dialectConfigurations.size());
        
        for (final DialectConfiguration dialectConfiguration : dialectConfigurations) {

            final IDialect dialect = dialectConfiguration.getDialect();

            if (totalDialects.intValue() > 1) {
                logBuilder.line("[THYMELEAF] * Dialect [{} of {}]: {} ({})", new Object[]{Integer.valueOf(dialectIndex), totalDialects, dialect.getName(), dialect.getClass().getName()});
            } else {
                logBuilder.line("[THYMELEAF] * Dialect: {} ({})", dialect.getName(), dialect.getClass().getName());
            }

            String dialectPrefix = null;
            if (dialect instanceof IProcessorDialect) {
                dialectPrefix = (dialectConfiguration.isPrefixSpecified()? dialectConfiguration.getPrefix() : ((IProcessorDialect) dialect).getPrefix());
                logBuilder.line("[THYMELEAF]     * Prefix: \"{}\"", (dialectPrefix != null ? dialectPrefix : "(none)"));
            }

            if (configLogger.isDebugEnabled()) {
                printDebugConfiguration(logBuilder, dialect, dialectPrefix);
            }
            
            dialectIndex++;
            
        }

        logBuilder.end("[THYMELEAF] TEMPLATE ENGINE CONFIGURED OK");

        /*
         * The following condition makes sense because contents in each case will differ a lot.
         */
        if (configLogger.isTraceEnabled()) {
            configLogger.trace(logBuilder.toString());
        } else if (configLogger.isDebugEnabled()) {
            configLogger.debug(logBuilder.toString());
        }
        
    }
    
    
    
    
    private static void printDebugConfiguration(final ConfigLogBuilder logBuilder, final IDialect idialect, final String dialectPrefix) {

        if (idialect instanceof IProcessorDialect) {

            final IProcessorDialect dialect = (IProcessorDialect)idialect;

            final Set processors = dialect.getProcessors(dialectPrefix);
            printProcessorsForTemplateMode(logBuilder, processors, TemplateMode.HTML);
            printProcessorsForTemplateMode(logBuilder, processors, TemplateMode.XML);
            printProcessorsForTemplateMode(logBuilder, processors, TemplateMode.TEXT);
            printProcessorsForTemplateMode(logBuilder, processors, TemplateMode.JAVASCRIPT);
            printProcessorsForTemplateMode(logBuilder, processors, TemplateMode.CSS);
            printProcessorsForTemplateMode(logBuilder, processors, TemplateMode.RAW);

        }

        if (idialect instanceof IPreProcessorDialect) {

            final IPreProcessorDialect dialect = (IPreProcessorDialect)idialect;

            final Set preProcessors = dialect.getPreProcessors();
            printPreProcessorsForTemplateMode(logBuilder, preProcessors, TemplateMode.HTML);
            printPreProcessorsForTemplateMode(logBuilder, preProcessors, TemplateMode.XML);
            printPreProcessorsForTemplateMode(logBuilder, preProcessors, TemplateMode.TEXT);
            printPreProcessorsForTemplateMode(logBuilder, preProcessors, TemplateMode.JAVASCRIPT);
            printPreProcessorsForTemplateMode(logBuilder, preProcessors, TemplateMode.CSS);
            printPreProcessorsForTemplateMode(logBuilder, preProcessors, TemplateMode.RAW);

        }

        if (idialect instanceof IPostProcessorDialect) {

            final IPostProcessorDialect dialect = (IPostProcessorDialect)idialect;

            final Set postProcessors = dialect.getPostProcessors();
            printPostProcessorsForTemplateMode(logBuilder, postProcessors, TemplateMode.HTML);
            printPostProcessorsForTemplateMode(logBuilder, postProcessors, TemplateMode.XML);
            printPostProcessorsForTemplateMode(logBuilder, postProcessors, TemplateMode.TEXT);
            printPostProcessorsForTemplateMode(logBuilder, postProcessors, TemplateMode.JAVASCRIPT);
            printPostProcessorsForTemplateMode(logBuilder, postProcessors, TemplateMode.CSS);
            printPostProcessorsForTemplateMode(logBuilder, postProcessors, TemplateMode.RAW);

        }

        if (idialect instanceof IExpressionObjectDialect) {

            final IExpressionObjectDialect dialect = (IExpressionObjectDialect)idialect;

            final IExpressionObjectFactory expressionObjectFactory = dialect.getExpressionObjectFactory();
            if (expressionObjectFactory != null) {

                final Set expressionObjectNames = expressionObjectFactory.getAllExpressionObjectNames();
                if (expressionObjectNames != null && !expressionObjectNames.isEmpty()) {
                    logBuilder.line("[THYMELEAF]     * Expression Objects:");
                    for (final String expressionObjectName : expressionObjectNames) {
                        logBuilder.line("[THYMELEAF]         * #{}", new Object[] {expressionObjectName});
                    }
                }

            }

        }

        if (idialect instanceof IExecutionAttributeDialect) {

            final IExecutionAttributeDialect dialect = (IExecutionAttributeDialect)idialect;

            final Map executionAttributes = dialect.getExecutionAttributes();
            if (executionAttributes != null && !executionAttributes.isEmpty()) {
                logBuilder.line("[THYMELEAF]     * Execution Attributes:");
                for (final Map.Entry executionAttributesEntry : executionAttributes.entrySet()) {
                    final String attrName = executionAttributesEntry.getKey();
                    final String attrValue =
                            (executionAttributesEntry.getValue() == null? null : executionAttributesEntry.getValue().toString());
                    logBuilder.line("[THYMELEAF]         * \"{}\": {}", new Object[] {attrName, attrValue});
                }
            }

        }



    }





    private static void printProcessorsForTemplateMode(final ConfigLogBuilder logBuilder, final Set processors, final TemplateMode templateMode) {

        if (processors == null || processors.isEmpty()) {
            return;
        }

        final List cdataSectionProcessors = new ArrayList();
        final List commentProcessors = new ArrayList();
        final List docTypeProcessors = new ArrayList();
        final List elementTagProcessors = new ArrayList();
        final List elementModelProcessors = new ArrayList();
        final List processingInstructionProcessors = new ArrayList();
        final List textProcessors = new ArrayList();
        final List xmlDeclarationProcessors = new ArrayList();

        boolean processorsForTemplateModeExist = false;
        for (final IProcessor processor : processors) {

            if (!templateMode.equals(processor.getTemplateMode())) {
                continue;
            }
            processorsForTemplateModeExist = true;

            if (processor instanceof ICDATASectionProcessor) {
                cdataSectionProcessors.add((ICDATASectionProcessor) processor);
            } else if (processor instanceof ICommentProcessor) {
                commentProcessors.add((ICommentProcessor) processor);
            } else if (processor instanceof IDocTypeProcessor) {
                docTypeProcessors.add((IDocTypeProcessor) processor);
            } else if (processor instanceof IElementTagProcessor) {
                elementTagProcessors.add((IElementTagProcessor) processor);
            } else if (processor instanceof IElementModelProcessor) {
                elementModelProcessors.add((IElementModelProcessor) processor);
            } else if (processor instanceof IProcessingInstructionProcessor) {
                processingInstructionProcessors.add((IProcessingInstructionProcessor) processor);
            } else if (processor instanceof ITextProcessor) {
                textProcessors.add((ITextProcessor) processor);
            } else if (processor instanceof IXMLDeclarationProcessor) {
                xmlDeclarationProcessors.add((IXMLDeclarationProcessor) processor);
            }

        }

        if (!processorsForTemplateModeExist) {
            // Nothing to show, there are no processors for this template mode
            return;
        }

        logBuilder.line("[THYMELEAF]     * Processors for Template Mode: {}", templateMode);

        Collections.sort(cdataSectionProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);
        Collections.sort(commentProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);
        Collections.sort(docTypeProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);
        Collections.sort(elementTagProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);
        Collections.sort(elementModelProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);
        Collections.sort(processingInstructionProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);
        Collections.sort(textProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);
        Collections.sort(xmlDeclarationProcessors, ProcessorComparators.PROCESSOR_COMPARATOR);

        if (!elementTagProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * Element Tag Processors by [matching element and attribute name] [precedence]:");
            for (final IElementTagProcessor processor : elementTagProcessors) {
                final MatchingElementName matchingElementName = processor.getMatchingElementName();
                final MatchingAttributeName matchingAttributeName = processor.getMatchingAttributeName();
                final String elementName = (matchingElementName == null? "*" : matchingElementName.toString());
                final String attributeName = (matchingAttributeName == null? "*" : matchingAttributeName.toString());
                logBuilder.line("[THYMELEAF]             * [{} {}] [{}]: {}",
                        new Object[] {elementName, attributeName, Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }
        if (!elementModelProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * Element Model Processors by [matching element and attribute name] [precedence]:");
            for (final IElementModelProcessor processor : elementModelProcessors) {
                final MatchingElementName matchingElementName = processor.getMatchingElementName();
                final MatchingAttributeName matchingAttributeName = processor.getMatchingAttributeName();
                final String elementName = (matchingElementName == null? "*" : matchingElementName.toString());
                final String attributeName = (matchingAttributeName == null? "*" : matchingAttributeName.toString());
                logBuilder.line("[THYMELEAF]             * [{} {}] [{}]: {}",
                        new Object[] {elementName, attributeName, Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }
        if (!textProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * Text Processors by [precedence]:");
            for (final ITextProcessor processor : textProcessors) {
                logBuilder.line("[THYMELEAF]             * [{}]: {}",
                        new Object[] {Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }
        if (!docTypeProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * DOCTYPE Processors by [precedence]:");
            for (final IDocTypeProcessor processor : docTypeProcessors) {
                logBuilder.line("[THYMELEAF]             * [{}]: {}",
                        new Object[] {Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }
        if (!cdataSectionProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * CDATA Section Processors by [precedence]:");
            for (final ICDATASectionProcessor processor : cdataSectionProcessors) {
                logBuilder.line("[THYMELEAF]             * [{}]: {}",
                        new Object[] {Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }
        if (!commentProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * Comment Processors by [precedence]:");
            for (final ICommentProcessor processor : commentProcessors) {
                logBuilder.line("[THYMELEAF]             * [{}]: {}",
                        new Object[] {Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }
        if (!xmlDeclarationProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * XML Declaration Processors by [precedence]:");
            for (final IXMLDeclarationProcessor processor : xmlDeclarationProcessors) {
                logBuilder.line("[THYMELEAF]             * [{}]: {}",
                        new Object[] {Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }
        if (!processingInstructionProcessors.isEmpty()) {
            logBuilder.line("[THYMELEAF]         * Processing Instruction Processors by [precedence]:");
            for (final IProcessingInstructionProcessor processor : processingInstructionProcessors) {
                logBuilder.line("[THYMELEAF]             * [{}]: {}",
                        new Object[] {Integer.valueOf(processor.getPrecedence()), processor.getClass().getName()});
            }
        }

    }




    private static void printPreProcessorsForTemplateMode(final ConfigLogBuilder logBuilder, final Set preProcessors, final TemplateMode templateMode) {

        if (preProcessors == null || preProcessors.isEmpty()) {
            return;
        }

        final List preProcessorsForTemplateMode = new ArrayList();

        for (final IPreProcessor preProcessor : preProcessors) {
            if (!templateMode.equals(preProcessor.getTemplateMode())) {
                continue;
            }
            preProcessorsForTemplateMode.add(preProcessor);
        }

        if (preProcessorsForTemplateMode.isEmpty()) {
            // Nothing to show, there are no artifacts for this template mode
            return;
        }

        Collections.sort(preProcessorsForTemplateMode, ProcessorComparators.PRE_PROCESSOR_COMPARATOR);

        logBuilder.line("[THYMELEAF]     * Pre-Processors for Template Mode: {} by [precedence]", templateMode);
        for (final IPreProcessor preProcessor : preProcessorsForTemplateMode) {
            logBuilder.line("[THYMELEAF]             * [{}]: {}",
                    new Object[] {Integer.valueOf(preProcessor.getPrecedence()), preProcessor.getClass().getName()});
        }

    }




    private static void printPostProcessorsForTemplateMode(final ConfigLogBuilder logBuilder, final Set postProcessors, final TemplateMode templateMode) {

        if (postProcessors == null || postProcessors.isEmpty()) {
            return;
        }

        final List postProcessorsForTemplateMode = new ArrayList();

        for (final IPostProcessor postProcessor : postProcessors) {
            if (!templateMode.equals(postProcessor.getTemplateMode())) {
                continue;
            }
            postProcessorsForTemplateMode.add(postProcessor);
        }

        if (postProcessorsForTemplateMode.isEmpty()) {
            // Nothing to show, there are no artifacts for this template mode
            return;
        }

        Collections.sort(postProcessorsForTemplateMode, ProcessorComparators.POST_PROCESSOR_COMPARATOR);

        logBuilder.line("[THYMELEAF]     * Post-Processors for Template Mode: {} by [precedence]", templateMode);
        for (final IPostProcessor postProcessor : postProcessorsForTemplateMode) {
            logBuilder.line("[THYMELEAF]             * [{}]: {}",
                    new Object[]{Integer.valueOf(postProcessor.getPrecedence()), postProcessor.getClass().getName()});
        }

    }



    
    
    private static final class ConfigLogBuilder {
        
        private static final String PLACEHOLDER = "\\{\\}";
        private final StringBuilder strBuilder;
        
        protected ConfigLogBuilder() {
            super();
            this.strBuilder = new StringBuilder();
        }
        
        protected void end(final String line) {
            this.strBuilder.append(line);
        }
        
        protected void line(final String line) {
            this.strBuilder.append(line).append("\n");
        }
        
        protected void line(final String line, final Object p1) {
            this.strBuilder.append(replace(line, p1)).append("\n");
        }
        
        protected void line(final String line, final Object p1, final Object p2) {
            this.strBuilder.append(replace(replace(line, p1), p2)).append("\n");
        }
        
        protected void line(final String line, final Object[] pArr) {
            String newLine = line;
            for (final Object aPArr : pArr) {
                newLine = replace(newLine, aPArr);
            }
            this.strBuilder.append(newLine).append("\n");
        }
        
        @Override
        public String toString() {
            return this.strBuilder.toString();
        }
        
        private String replace(final String str, final Object replacement) {
            return str.replaceFirst(PLACEHOLDER, (replacement == null? "" : param(replacement)));
        }
        
        private String param(final Object p) {
            if (p == null) {
                return null;
            }
            return p.toString().replaceAll("\\$", "\\.");
        }
        
    }
    
    
    
    
    private ConfigurationPrinterHelper() {
        super();
    }



}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy