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

org.grails.web.converters.configuration.ConvertersConfigurationInitializer Maven / Gradle / Ivy

There is a newer version: 2023.0.2
Show newest version
/*
 * Copyright 2004-2022 the original author or authors.
 *
 * 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
 *
 *      https://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.grails.web.converters.configuration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;

import grails.config.Config;
import grails.converters.JSON;
import grails.converters.XML;
import grails.core.GrailsApplication;
import grails.core.support.GrailsApplicationAware;
import grails.core.support.proxy.DefaultProxyHandler;
import grails.core.support.proxy.ProxyHandler;

import org.grails.config.PropertySourcesConfig;
import org.grails.web.converters.Converter;
import org.grails.web.converters.marshaller.ObjectMarshaller;
import org.grails.web.converters.marshaller.ProxyUnwrappingMarshaller;

/**
 * @author Siegfried Puchbauer
 * @author Michael Yan
 * @since 1.1
 */
public class ConvertersConfigurationInitializer implements ApplicationContextAware, GrailsApplicationAware,
        InitializingBean, SmartInitializingSingleton {

    public static final Log logger = LogFactory.getLog(ConvertersConfigurationInitializer.class);

    public static final String SETTING_CONVERTERS_JSON_DATE = "grails.converters.json.date";

    public static final String SETTING_CONVERTERS_JSON_DEFAULT_DEEP = "grails.converters.json.default.deep";

    public static final String SETTING_CONVERTERS_ENCODING = "grails.converters.encoding";

    public static final String SETTING_CONVERTERS_CIRCULAR_REFERENCE_BEHAVIOUR = "grails.converters.default.circular.reference.behaviour";

    public static final String SETTING_CONVERTERS_JSON_CIRCULAR_REFERENCE_BEHAVIOUR = "grails.converters.json.circular.reference.behaviour";

    public static final String SETTING_CONVERTERS_PRETTY_PRINT = "grails.converters.default.pretty.print";

    public static final String SETTING_CONVERTERS_JSON_PRETTY_PRINT = "grails.converters.json.pretty.print";

    public static final String SETTING_CONVERTERS_JSON_CACHE_OBJECTS = "grails.converters.json.cacheObjectMarshallerSelectionByClass";

    public static final String SETTING_CONVERTERS_XML_DEEP = "grails.converters.xml.default.deep";

    private ApplicationContext applicationContext;

    private GrailsApplication grailsApplication;

    public ApplicationContext getApplicationContext() {
        return this.applicationContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.applicationContext, "ApplicationContext must be set");
    }

    @Override
    public void afterSingletonsInstantiated() {
        initialize();
    }

    public void initialize() {
        if (logger.isDebugEnabled()) {
            logger.debug("Initializing Converters Default Configurations...");
        }
        initJSONConfiguration();
        initXMLConfiguration();
        initDeepJSONConfiguration();
        initDeepXMLConfiguration();
    }

    private void initJSONConfiguration() {
        if (logger.isDebugEnabled()) {
            logger.debug("Initializing default JSON Converters Configuration...");
        }

        List> marshallers = new ArrayList<>();
        marshallers.addAll(getPreviouslyConfiguredMarshallers(JSON.class));
        marshallers.add(new org.grails.web.converters.marshaller.json.ArrayMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.json.ByteArrayMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.json.CollectionMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.json.MapMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.json.EnumMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.ProxyUnwrappingMarshaller<>());

        Config grailsConfig = getGrailsConfig();

        if ("javascript".equals(grailsConfig.getProperty(SETTING_CONVERTERS_JSON_DATE,
                String.class, "default", Arrays.asList("javascript", "default")))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Using Javascript JSON Date Marshaller.");
            }
            marshallers.add(new org.grails.web.converters.marshaller.json.JavascriptDateMarshaller());
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Using default JSON Date Marshaller");
            }
            marshallers.add(new org.grails.web.converters.marshaller.json.DateMarshaller());
        }
        marshallers.add(new org.grails.web.converters.marshaller.json.ToStringBeanMarshaller());

        boolean includeDomainVersion = includeDomainVersionProperty(grailsConfig, "json");
        boolean includeDomainClassName = includeDomainClassProperty(grailsConfig, "json");
        ProxyHandler proxyHandler = getProxyHandler();
        if (grailsConfig.getProperty(SETTING_CONVERTERS_JSON_DEFAULT_DEEP, Boolean.class, false)) {
            logger.debug("Using DeepDomainClassMarshaller as default.");
            marshallers.add(new org.grails.web.converters.marshaller.json.DeepDomainClassMarshaller(
                    includeDomainVersion, includeDomainClassName, proxyHandler, this.grailsApplication));
        }
        else {
            marshallers.add(new org.grails.web.converters.marshaller.json.DomainClassMarshaller(
                    includeDomainVersion, includeDomainClassName, proxyHandler, this.grailsApplication));
        }
        marshallers.add(new org.grails.web.converters.marshaller.json.GroovyBeanMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller());

        DefaultConverterConfiguration cfg = new DefaultConverterConfiguration(marshallers, proxyHandler);
        cfg.setEncoding(grailsConfig.getProperty(SETTING_CONVERTERS_ENCODING, "UTF-8"));
        String defaultCirRefBehaviour = grailsConfig.getProperty(SETTING_CONVERTERS_CIRCULAR_REFERENCE_BEHAVIOUR, "DEFAULT");
        cfg.setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour.valueOf(
                grailsConfig.getProperty(SETTING_CONVERTERS_JSON_CIRCULAR_REFERENCE_BEHAVIOUR, String.class,
                        defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues())));

        Boolean defaultPrettyPrint = grailsConfig.getProperty(SETTING_CONVERTERS_PRETTY_PRINT, Boolean.class, false);
        Boolean prettyPrint = grailsConfig.getProperty(SETTING_CONVERTERS_JSON_PRETTY_PRINT, Boolean.class, defaultPrettyPrint);
        cfg.setPrettyPrint(prettyPrint);
        cfg.setCacheObjectMarshallerByClass(grailsConfig.getProperty(SETTING_CONVERTERS_JSON_CACHE_OBJECTS, Boolean.class, true));

        registerObjectMarshallersFromApplicationContext(cfg, JSON.class);

        ConvertersConfigurationHolder.setDefaultConfiguration(JSON.class, new ChainedConverterConfiguration<>(cfg, proxyHandler));
    }

    private Config getGrailsConfig() {
        Config grailsConfig;
        if (this.grailsApplication != null) {
            grailsConfig = this.grailsApplication.getConfig();
        }
        else {
            // empty config, will trigger defaults
            grailsConfig = new PropertySourcesConfig();
        }
        return grailsConfig;
    }

    private void initDeepJSONConfiguration() {
        DefaultConverterConfiguration deepConfig = new DefaultConverterConfiguration<>(
                ConvertersConfigurationHolder.getConverterConfiguration(JSON.class), getProxyHandler());
        deepConfig.registerObjectMarshaller(new org.grails.web.converters.marshaller.json.DeepDomainClassMarshaller(
                includeDomainVersionProperty(getGrailsConfig(), "json"),
                includeDomainClassProperty(getGrailsConfig(), "json"),
                getProxyHandler(), this.grailsApplication));
        ConvertersConfigurationHolder.setNamedConverterConfiguration(JSON.class, "deep", deepConfig);
    }

    private void initXMLConfiguration() {
        logger.debug("Initializing default XML Converters Configuration...");

        List> marshallers = new ArrayList<>();
        marshallers.addAll(getPreviouslyConfiguredMarshallers(XML.class));
        marshallers.add(new org.grails.web.converters.marshaller.xml.Base64ByteArrayMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.xml.ArrayMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.xml.CollectionMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.xml.MapMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.xml.EnumMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.xml.DateMarshaller());
        marshallers.add(new ProxyUnwrappingMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.xml.ToStringBeanMarshaller());
        ProxyHandler proxyHandler = getProxyHandler();

        Config grailsConfig = getGrailsConfig();

        boolean includeDomainVersion = includeDomainVersionProperty(grailsConfig, "xml");
        if (grailsConfig.getProperty(SETTING_CONVERTERS_XML_DEEP, Boolean.class, false)) {
            marshallers.add(new org.grails.web.converters.marshaller.xml.DeepDomainClassMarshaller(
                    includeDomainVersion, proxyHandler, this.grailsApplication));
        }
        else {
            marshallers.add(new org.grails.web.converters.marshaller.xml.DomainClassMarshaller(
                    includeDomainVersion, proxyHandler, this.grailsApplication));
        }
        marshallers.add(new org.grails.web.converters.marshaller.xml.GroovyBeanMarshaller());
        marshallers.add(new org.grails.web.converters.marshaller.xml.GenericJavaBeanMarshaller());

        DefaultConverterConfiguration cfg = new DefaultConverterConfiguration(marshallers, proxyHandler);
        cfg.setEncoding(grailsConfig.getProperty(SETTING_CONVERTERS_ENCODING, "UTF-8"));
        String defaultCirRefBehaviour = grailsConfig.getProperty(SETTING_CONVERTERS_CIRCULAR_REFERENCE_BEHAVIOUR, "DEFAULT");
        cfg.setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour.valueOf(
                grailsConfig.getProperty("grails.converters.xml.circular.reference.behaviour", String.class,
                        defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues())));

        Boolean defaultPrettyPrint = grailsConfig.getProperty(SETTING_CONVERTERS_PRETTY_PRINT, Boolean.class, false);
        Boolean prettyPrint = grailsConfig.getProperty("grails.converters.xml.pretty.print", Boolean.class, defaultPrettyPrint);
        cfg.setPrettyPrint(prettyPrint);
        cfg.setCacheObjectMarshallerByClass(
                grailsConfig.getProperty("grails.converters.xml.cacheObjectMarshallerSelectionByClass", Boolean.class, true));
        registerObjectMarshallersFromApplicationContext(cfg, XML.class);
        ConvertersConfigurationHolder.setDefaultConfiguration(XML.class, new ChainedConverterConfiguration(cfg, proxyHandler));
    }

    private ProxyHandler getProxyHandler() {
        ProxyHandler proxyHandler;
        if (this.applicationContext != null) {
            proxyHandler = this.applicationContext.getBean(ProxyHandler.class);
        }
        else {
            proxyHandler = new DefaultProxyHandler();
        }
        return proxyHandler;
    }

    private void initDeepXMLConfiguration() {
        DefaultConverterConfiguration deepConfig = new DefaultConverterConfiguration<>(
                ConvertersConfigurationHolder.getConverterConfiguration(XML.class), getProxyHandler());
        deepConfig.registerObjectMarshaller(new org.grails.web.converters.marshaller.xml.DeepDomainClassMarshaller(
                includeDomainVersionProperty(getGrailsConfig(), "xml"),
                includeDomainClassProperty(getGrailsConfig(), "xml"), getProxyHandler(), this.grailsApplication));
        ConvertersConfigurationHolder.setNamedConverterConfiguration(XML.class, "deep", deepConfig);
    }

    private boolean includeDomainVersionProperty(Config grailsConfig, String converterType) {
        return grailsConfig.getProperty(String.format("grails.converters.%s.domain.include.version", converterType),
                Boolean.class, grailsConfig.getProperty("grails.converters.domain.include.version", Boolean.class, false));
    }

    private boolean includeDomainClassProperty(Config grailsConfig, String converterType) {
        return grailsConfig.getProperty(String.format("grails.converters.%s.domain.include.class", converterType),
                Boolean.class, grailsConfig.getProperty("grails.converters.domain.include.class", Boolean.class, false));
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private  void registerObjectMarshallersFromApplicationContext(
            DefaultConverterConfiguration cfg, Class converterClass) {

        if (this.applicationContext == null) {
            return;
        }

        for (ObjectMarshallerRegisterer omr : this.applicationContext.getBeansOfType(ObjectMarshallerRegisterer.class).values()) {
            if (omr.getConverterClass() == converterClass) {
                cfg.registerObjectMarshaller(omr.getMarshaller(), omr.getPriority());
            }
        }
    }

    @Override
    public void setGrailsApplication(GrailsApplication grailsApplication) {
        this.grailsApplication = grailsApplication;
    }

    private  List> getPreviouslyConfiguredMarshallers(Class converterClass) {
        ConverterConfiguration previousConfiguration = ConvertersConfigurationHolder.getConverterConfiguration(converterClass);
        return previousConfiguration.getOrderedObjectMarshallers();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy