2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.remote
.view
;
11 import java
.io
.PrintWriter
;
12 import java
.util
.Collection
;
15 import javax
.servlet
.http
.HttpServletRequest
;
16 import javax
.servlet
.http
.HttpServletResponse
;
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
;
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
;
33 public class JsonView
extends BaseView
implements View
{
36 optOut_BEANUTILS_520();
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.
43 * see https://github.com/apache/commons-beanutils/pull/7
45 static private void optOut_BEANUTILS_520() {
46 final BeanUtilsBean bub
= new BeanUtilsBean();
47 bub
.getPropertyUtils().removeBeanIntrospector(SuppressPropertiesBeanIntrospector
.SUPPRESS_CLASS
);
48 BeanUtilsBean
.setInstance(bub
);
51 public static final Logger logger
= LogManager
.getLogger(JsonView
.class);
53 private JsonConfig jsonConfig
;
55 private DataSourceProperties dataSourceProperties
;
57 public DataSourceProperties
getDataSourceProperties() {
58 return dataSourceProperties
;
61 public void setDataSourceProperties(DataSourceProperties dataSourceProperties
) {
62 this.dataSourceProperties
= dataSourceProperties
;
66 JSON("application/json"),
67 XML("application/xml");
69 private final String contentType
;
71 Type(String contentType
){
72 this.contentType
= contentType
;
75 public String
getContentType(){
80 private Type type
= Type
.JSON
;
82 private String xsl
= null;
84 public void setXsl(String xsl
) {
88 public String
getXsl() {
92 public Type
getType() {
97 * Default is Type.JSON
100 public void setType(Type type
) {
104 public void setJsonConfig(JsonConfig jsonConfig
) {
105 this.jsonConfig
= jsonConfig
;
109 public String
getContentType() {
110 return type
.getContentType();
114 public void render(Object entity
, PrintWriter writer
, String jsonpCallback
, HttpServletRequest request
, HttpServletResponse response
) throws Exception
{
116 String contextPath
= null;
118 if (request
!= null) {
119 contextPath
= request
.getContextPath();
122 if(jsonConfig
== null){
123 logger
.error("The jsonConfig must not be null. It must be set in the applicationContext.");
126 // option to skip json processing for debugging purposes, see #4925
127 if(System
.getProperty("SkipJSON") == null) {
129 // create JSON Object
131 // long start = System.currentTimeMillis();
132 boolean isCollectionType
= false;
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()+"}");
146 jsonObj
= JSONObject
.fromObject(entity
, jsonConfig
);
148 // System.err.println("create JSON Object " + (System.currentTimeMillis() - start));
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
;
157 elementType
= c
.iterator().next().getClass();
159 xmlSerializer
.setObjectName(elementType
.getSimpleName());
160 } else if(entity
!= null){
161 xmlSerializer
.setObjectName(entity
.getClass().getSimpleName());
163 String xml
= xmlSerializer
.write( jsonObj
);
164 if(type
.equals(Type
.XML
) && xsl
!= null){
166 if(contextPath
== null){
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
);
176 if(jsonpCallback
!= null){
177 // writer.append(jsonpCallback).append("(").append(jsonObj.toString()).append(");");
179 writer
.append(jsonObj
.toString());
182 //TODO resp.setContentType(type);
185 writer
.append("SkipJSON mode detected, this is for debugging only! Please contact the adminitrator.");
192 public void render(Map model
, HttpServletRequest request
, HttpServletResponse response
) throws Exception
{
194 // Retrieve data from model
195 Object entity
= getResponseData(model
);
198 response
.setContentType(type
.getContentType());
200 PrintWriter writer
= response
.getWriter();
202 // read jsonp parameter from the request
203 String jsonpCallback
= JsonpUtil
.readJsonpCallback(request
);
206 render(entity
, writer
, jsonpCallback
, request
, response
);