1 /*
2  * Copyright 2004-2008 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.codehaus.groovy.grails.web.converters.configuration;
17 
18 import grails.converters.JSON;
19 import grails.converters.XML;
20 import grails.util.GrailsConfig;
21 
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25 
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.codehaus.groovy.grails.support.proxy.DefaultProxyHandler;
29 import org.codehaus.groovy.grails.support.proxy.ProxyHandler;
30 import org.codehaus.groovy.grails.web.converters.Converter;
31 import org.codehaus.groovy.grails.web.converters.marshaller.ObjectMarshaller;
32 import org.codehaus.groovy.grails.web.converters.marshaller.ProxyUnwrappingMarshaller;
33 import org.springframework.context.ApplicationContext;
34 import org.springframework.context.ApplicationContextAware;
35 
36 /**
37  * @author Siegfried Puchbauer
38  * @since 1.1
39  */
40 public class ConvertersConfigurationInitializer implements ApplicationContextAware {
41 
42     private ApplicationContext applicationContext;
43 
getApplicationContext()44     public ApplicationContext getApplicationContext() {
45         return applicationContext;
46     }
47 
setApplicationContext(ApplicationContext applicationContext)48     public void setApplicationContext(ApplicationContext applicationContext) {
49         this.applicationContext = applicationContext;
50     }
51 
52     public final Log LOG = LogFactory.getLog(ConvertersConfigurationInitializer.class);
53 
initialize()54     public void initialize() {
55         LOG.debug("Initializing Converters Default Configurations...");
56         initJSONConfiguration();
57         initXMLConfiguration();
58         initDeepJSONConfiguration();
59         initDeepXMLConfiguration();
60     }
61 
initJSONConfiguration()62     private void initJSONConfiguration() {
63         LOG.debug("Initializing default JSON Converters Configuration...");
64 
65         List<ObjectMarshaller<JSON>> marshallers = new ArrayList<ObjectMarshaller<JSON>>();
66         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.ArrayMarshaller());
67         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.ByteArrayMarshaller());
68         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.CollectionMarshaller());
69         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.MapMarshaller());
70         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.EnumMarshaller());
71         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.ProxyUnwrappingMarshaller<JSON>());
72 
73         if ("javascript".equals(GrailsConfig.get("grails.converters.json.date", "default", Arrays.asList("javascript", "default")))) {
74             LOG.debug("Using Javascript JSON Date Marshaller.");
75             marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.JavascriptDateMarshaller());
76         }
77         else {
78             LOG.debug("Using default JSON Date Marshaller");
79             marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.DateMarshaller());
80         }
81         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.ToStringBeanMarshaller());
82 
83         boolean includeDomainVersion = includeDomainVersionProperty("json");
84         ProxyHandler proxyHandler = getProxyHandler();
85         if (GrailsConfig.get("grails.converters.json.default.deep", false)) {
86             LOG.debug("Using DeepDomainClassMarshaller as default.");
87             marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.DeepDomainClassMarshaller(includeDomainVersion, proxyHandler));
88         }
89         else {
90             marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller(includeDomainVersion, proxyHandler));
91         }
92         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.GroovyBeanMarshaller());
93         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller());
94 
95         DefaultConverterConfiguration<JSON> cfg = new DefaultConverterConfiguration<JSON>(marshallers, proxyHandler);
96         cfg.setEncoding(GrailsConfig.get("grails.converters.encoding", "UTF-8"));
97         String defaultCirRefBehaviour = GrailsConfig.get("grails.converters.default.circular.reference.behaviour", "DEFAULT");
98         cfg.setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour.valueOf(
99                 GrailsConfig.get("grails.converters.json.circular.reference.behaviour", defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues())
100         ));
101 
102         Boolean defaultPrettyPrint = GrailsConfig.get("grails.converters.default.pretty.print", false);
103         Boolean prettyPrint = GrailsConfig.get("grails.converters.json.pretty.print", defaultPrettyPrint);
104         cfg.setPrettyPrint(prettyPrint);
105 
106         registerObjectMarshallersFromApplicationContext(cfg, JSON.class);
107 
108         ConvertersConfigurationHolder.setDefaultConfiguration(JSON.class, new ChainedConverterConfiguration<JSON>(cfg, proxyHandler));
109     }
110 
initDeepJSONConfiguration()111     private void initDeepJSONConfiguration() {
112         DefaultConverterConfiguration<JSON> deepConfig = new DefaultConverterConfiguration<JSON>(ConvertersConfigurationHolder.getConverterConfiguration(JSON.class), getProxyHandler());
113         deepConfig.registerObjectMarshaller(new org.codehaus.groovy.grails.web.converters.marshaller.json.DeepDomainClassMarshaller(includeDomainVersionProperty("json"), getProxyHandler()));
114         ConvertersConfigurationHolder.setNamedConverterConfiguration(JSON.class, "deep", deepConfig);
115     }
116 
initXMLConfiguration()117     private void initXMLConfiguration() {
118         LOG.debug("Initializing default XML Converters Configuration...");
119 
120         List<ObjectMarshaller<XML>> marshallers = new ArrayList<ObjectMarshaller<XML>>();
121         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.ArrayMarshaller());
122         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.CollectionMarshaller());
123         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.MapMarshaller());
124         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.EnumMarshaller());
125         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.DateMarshaller());
126         marshallers.add(new ProxyUnwrappingMarshaller<XML>());
127         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.ToStringBeanMarshaller());
128         ProxyHandler proxyHandler = getProxyHandler();
129 
130         boolean includeDomainVersion = includeDomainVersionProperty("xml");
131         if (GrailsConfig.get("grails.converters.xml.default.deep", false)) {
132             marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.DeepDomainClassMarshaller(includeDomainVersion, proxyHandler));
133         }
134         else {
135             marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.DomainClassMarshaller(includeDomainVersion, proxyHandler));
136         }
137         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.GroovyBeanMarshaller());
138         marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.xml.GenericJavaBeanMarshaller());
139 
140         DefaultConverterConfiguration<XML> cfg = new DefaultConverterConfiguration<XML>(marshallers,proxyHandler);
141         cfg.setEncoding(GrailsConfig.get("grails.converters.encoding", "UTF-8"));
142         String defaultCirRefBehaviour = GrailsConfig.get("grails.converters.default.circular.reference.behaviour", "DEFAULT");
143         cfg.setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour.valueOf(
144                 GrailsConfig.get("grails.converters.xml.circular.reference.behaviour", defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues())
145         ));
146 
147         Boolean defaultPrettyPrint = GrailsConfig.get("grails.converters.default.pretty.print", false);
148         Boolean prettyPrint = GrailsConfig.get("grails.converters.xml.pretty.print", defaultPrettyPrint);
149         cfg.setPrettyPrint(prettyPrint);
150         registerObjectMarshallersFromApplicationContext(cfg, XML.class);
151         ConvertersConfigurationHolder.setDefaultConfiguration(XML.class, new ChainedConverterConfiguration<XML>(cfg,proxyHandler));
152     }
153 
getProxyHandler()154     private ProxyHandler getProxyHandler() {
155         ProxyHandler proxyHandler;
156         if (applicationContext != null) {
157             proxyHandler = applicationContext.getBean(ProxyHandler.class);
158         }
159         else {
160             proxyHandler = new DefaultProxyHandler();
161         }
162         return proxyHandler;
163     }
164 
initDeepXMLConfiguration()165     private void initDeepXMLConfiguration() {
166         DefaultConverterConfiguration<XML> deepConfig = new DefaultConverterConfiguration<XML>(ConvertersConfigurationHolder.getConverterConfiguration(XML.class), getProxyHandler());
167         deepConfig.registerObjectMarshaller(new org.codehaus.groovy.grails.web.converters.marshaller.xml.DeepDomainClassMarshaller(includeDomainVersionProperty("xml"), getProxyHandler()));
168         ConvertersConfigurationHolder.setNamedConverterConfiguration(XML.class, "deep", deepConfig);
169     }
170 
includeDomainVersionProperty(String converterType)171     private boolean includeDomainVersionProperty(String converterType) {
172         return GrailsConfig.get(String.format("grails.converters.%s.domain.include.version", converterType),
173                 GrailsConfig.get("grails.converters.domain.include.version", false));
174     }
175 
176     @SuppressWarnings({ "unchecked", "rawtypes" })
registerObjectMarshallersFromApplicationContext( DefaultConverterConfiguration<C> cfg, Class<C> converterClass)177     private <C extends Converter> void registerObjectMarshallersFromApplicationContext(
178             DefaultConverterConfiguration<C> cfg, Class<C> converterClass) {
179 
180         if (applicationContext == null) {
181             return;
182         }
183 
184         for (Object o : applicationContext.getBeansOfType(ObjectMarshallerRegisterer.class).values()) {
185             ObjectMarshallerRegisterer omr = (ObjectMarshallerRegisterer) o;
186             if (omr.getConverterClass() == converterClass) {
187                 cfg.registerObjectMarshaller(omr.getMarshaller(), omr.getPriority());
188             }
189         }
190     }
191 }
192