cleanup
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / view / JsonView.java
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 }