Project

General

Profile

Download (6.82 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.remote.view;
10

    
11
import java.io.PrintWriter;
12
import java.util.Collection;
13
import java.util.Map;
14

    
15
import javax.servlet.http.HttpServletRequest;
16
import javax.servlet.http.HttpServletResponse;
17

    
18
import org.apache.commons.beanutils.BeanUtilsBean;
19
import org.apache.commons.beanutils.SuppressPropertiesBeanIntrospector;
20
import org.apache.logging.log4j.LogManager;
21
import org.apache.logging.log4j.Logger;
22
import org.springframework.web.servlet.View;
23

    
24
import eu.etaxonomy.cdm.opt.config.DataSourceProperties;
25
import eu.etaxonomy.cdm.remote.json.JsonpUtil;
26
import net.sf.json.JSON;
27
import net.sf.json.JSONArray;
28
import net.sf.json.JSONObject;
29
import net.sf.json.JsonConfig;
30
import net.sf.json.xml.XMLSerializer;
31

    
32

    
33
public class JsonView extends BaseView implements View {
34

    
35
    static {
36
        optOut_BEANUTILS_520();
37
    }
38

    
39
    /**
40
     * BEANUTILS-520 Fixes CVE-2014-0114: https://nvd.nist.gov/vuln/detail/CVE-2014-0114
41
     * This patch by default enables the SuppressPropertiesBeanIntrospector.SUPPRESS_CLASS.
42
     *
43
     * see https://github.com/apache/commons-beanutils/pull/7
44
     */
45
    static private void optOut_BEANUTILS_520() {
46
        final BeanUtilsBean bub = new BeanUtilsBean();
47
        bub.getPropertyUtils().removeBeanIntrospector(SuppressPropertiesBeanIntrospector.SUPPRESS_CLASS);
48
        BeanUtilsBean.setInstance(bub);
49
    }
50

    
51
    public static final Logger logger = LogManager.getLogger(JsonView.class);
52

    
53
    private JsonConfig jsonConfig;
54

    
55
    private DataSourceProperties dataSourceProperties;
56

    
57
    public DataSourceProperties getDataSourceProperties() {
58
        return dataSourceProperties;
59
    }
60

    
61
    public void setDataSourceProperties(DataSourceProperties dataSourceProperties) {
62
        this.dataSourceProperties = dataSourceProperties;
63
    }
64

    
65
    public enum Type{
66
        JSON("application/json"),
67
        XML("application/xml");
68

    
69
        private final String contentType;
70

    
71
        Type(String contentType){
72
            this.contentType = contentType;
73
        }
74

    
75
        public String getContentType(){
76
            return contentType;
77
        }
78
    }
79

    
80
    private Type type = Type.JSON;
81

    
82
    private String xsl = null;
83

    
84
    public void setXsl(String xsl) {
85
        this.xsl = xsl;
86
    }
87

    
88
    public String getXsl() {
89
        return xsl;
90
    }
91

    
92
    public Type getType() {
93
        return type;
94
    }
95

    
96
    /**
97
     * Default is Type.JSON
98
     * @param type
99
     */
100
    public void setType(Type type) {
101
        this.type = type;
102
    }
103

    
104
    public void setJsonConfig(JsonConfig jsonConfig) {
105
        this.jsonConfig = jsonConfig;
106
    }
107

    
108
    @Override
109
    public String getContentType() {
110
        return type.getContentType();
111
    }
112

    
113
    @Override
114
    public void render(Object entity, PrintWriter writer, String jsonpCallback, HttpServletRequest request, HttpServletResponse response) throws Exception {
115

    
116
        String contextPath = null;
117

    
118
        if (request != null) {
119
        	contextPath = request.getContextPath();
120
        }
121

    
122
        if(jsonConfig == null){
123
            logger.error("The jsonConfig must not be null. It must be set in the applicationContext.");
124
        }
125

    
126
        // option to skip json processing for debugging purposes, see #4925
127
        if(System.getProperty("SkipJSON") == null) {
128

    
129
            // create JSON Object
130

    
131
    //        long start = System.currentTimeMillis();
132
            boolean isCollectionType = false;
133
            JSON jsonObj;
134
            if (entity == null){
135
                jsonObj = JSONObject.fromObject("{}");
136
            } else if(Collection.class.isAssignableFrom(entity.getClass())){
137
                isCollectionType = true;
138
                jsonObj = JSONArray.fromObject(entity, jsonConfig);
139
            }else if(entity instanceof String){
140
                jsonObj = JSONObject.fromObject("{\"String\":\""+entity.toString().replace("\"", "\\\"")+"\"}");
141
            } else if(entity instanceof Integer){
142
                jsonObj = JSONObject.fromObject("{\"Integer\":"+((Integer)entity).intValue()+"}");
143
            } else if(entity instanceof Boolean){
144
                jsonObj = JSONObject.fromObject("{\"Boolean\":"+((Boolean)entity).toString()+"}");
145
            } else {
146
                jsonObj = JSONObject.fromObject(entity, jsonConfig);
147
            }
148
    //        System.err.println("create JSON Object " + (System.currentTimeMillis() - start));
149

    
150
            if(type.equals(Type.XML)){
151
                XMLSerializer xmlSerializer = new XMLSerializer();
152
                if(isCollectionType){
153
                    xmlSerializer.setArrayName(entity.getClass().getSimpleName());
154
                    Class<?> elementType = Object.class;
155
                    Collection<?> c = (Collection<?>)entity;
156
                    if(c.size() > 0){
157
                        elementType = c.iterator().next().getClass();
158
                    }
159
                    xmlSerializer.setObjectName(elementType.getSimpleName());
160
                } else if(entity != null){
161
                    xmlSerializer.setObjectName(entity.getClass().getSimpleName());
162
                }
163
                String xml = xmlSerializer.write( jsonObj );
164
                if(type.equals(Type.XML) && xsl != null){
165

    
166
                    if(contextPath == null){
167
                        contextPath = "";
168
                    }
169
                    String basepath = dataSourceProperties.getXslBasePath(contextPath + "/xsl");
170
                    String replace = "\r\n<?xml-stylesheet type=\"text/xsl\" href=\"" + basepath + "/" + xsl + "\"?>\r\n";
171
                    xml = xml.replaceFirst("\r\n", replace);
172
                }
173
                writer.append(xml);
174
            } else {
175
                // assuming json
176
                if(jsonpCallback != null){
177
                   // writer.append(jsonpCallback).append("(").append(jsonObj.toString()).append(");");
178
                } else {
179
                    writer.append(jsonObj.toString());
180
                }
181
            }
182
            //TODO resp.setContentType(type);
183

    
184
        } else {
185
            writer.append("SkipJSON mode detected, this is for debugging only! Please contact the adminitrator.");
186
            // END SkipJSON
187
        }
188
        writer.flush();
189
    }
190

    
191
    @Override
192
    public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
193

    
194
        // Retrieve data from model
195
        Object entity = getResponseData(model);
196

    
197
        // set content type
198
        response.setContentType(type.getContentType());
199

    
200
        PrintWriter writer = response.getWriter();
201

    
202
        // read jsonp parameter from the request
203
        String jsonpCallback = JsonpUtil.readJsonpCallback(request);
204

    
205
        // render
206
        render(entity, writer, jsonpCallback, request, response);
207
    }
208
}
(5-5/10)