1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.api;
17
18 import java.io.IOException;
19 import java.io.PrintWriter;
20 import java.io.StringWriter;
21 import java.text.SimpleDateFormat;
22 import java.util.Date;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.Map;
26
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.apache.commons.text.StringEscapeUtils;
30 import org.codelibs.core.CoreLibConstants;
31 import org.codelibs.core.lang.StringUtil;
32 import org.codelibs.fess.Constants;
33 import org.codelibs.fess.exception.InvalidAccessTokenException;
34 import org.codelibs.fess.util.ComponentUtil;
35 import org.lastaflute.web.util.LaRequestUtil;
36 import org.lastaflute.web.util.LaResponseUtil;
37
38 public abstract class BaseJsonApiManager extends BaseApiManager {
39
40 protected String mimeType = "application/json";
41
42 protected void writeJsonResponse(final int status, final String body, final Throwable t) {
43 if (t == null) {
44 writeJsonResponse(status, body, (String) null);
45 return;
46 }
47
48 if (t instanceof InvalidAccessTokenException) {
49 final InvalidAccessTokenException e = (InvalidAccessTokenException) t;
50 final HttpServletResponse response = LaResponseUtil.getResponse();
51 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
52 response.setHeader("WWW-Authenticate", "Bearer error=\"" + e.getType() + "\"");
53 }
54
55 final StringBuilder sb = new StringBuilder();
56 if (StringUtil.isBlank(t.getMessage())) {
57 sb.append(t.getClass().getName());
58 } else {
59 sb.append(t.getMessage());
60 }
61 final StringWriter sw = new StringWriter();
62 t.printStackTrace(new PrintWriter(sw));
63 sb.append(" [ ").append(sw.toString()).append(" ]");
64 try {
65 sw.close();
66 } catch (final IOException ignore) {}
67 writeJsonResponse(status, body, sb.toString());
68 }
69
70 protected void writeJsonResponse(final int status, final String body, final String errMsg) {
71 String content = null;
72 if (status == 0) {
73 if (StringUtil.isNotBlank(body)) {
74 content = body;
75 }
76 } else {
77 content = "\"message\":" + escapeJson(errMsg);
78 }
79 writeJsonResponse(status, content);
80 }
81
82 protected void writeJsonResponse(final int status, final String body) {
83 final String callback = LaRequestUtil.getRequest().getParameter("callback");
84 final boolean isJsonp = ComponentUtil.getFessConfig().isApiJsonpEnabled() && StringUtil.isNotBlank(callback);
85
86 final StringBuilder buf = new StringBuilder(1000);
87 if (isJsonp) {
88 buf.append(escapeCallbackName(callback));
89 buf.append('(');
90 }
91 buf.append("{\"response\":");
92 buf.append("{\"version\":\"");
93 buf.append(ComponentUtil.getSystemHelper().getProductVersion());
94 buf.append("\",");
95 buf.append("\"status\":");
96 buf.append(status);
97 if (StringUtil.isNotBlank(body)) {
98 buf.append(',');
99 buf.append(body);
100 }
101 buf.append('}');
102 buf.append('}');
103 if (isJsonp) {
104 buf.append(')');
105 }
106 write(buf.toString(), mimeType, Constants.UTF_8);
107
108 }
109
110 protected String escapeCallbackName(final String callbackName) {
111 return "/**/" + callbackName.replaceAll("[^0-9a-zA-Z_\\$\\.]", StringUtil.EMPTY);
112 }
113
114 protected String escapeJson(final Object obj) {
115 if (obj == null) {
116 return "null";
117 }
118
119 final StringBuilder buf = new StringBuilder(255);
120 if (obj instanceof String[]) {
121 buf.append('[');
122 boolean first = true;
123 for (final Object child : (String[]) obj) {
124 if (first) {
125 first = false;
126 } else {
127 buf.append(',');
128 }
129 buf.append(escapeJson(child));
130 }
131 buf.append(']');
132 } else if (obj instanceof List<?>) {
133 buf.append('[');
134 boolean first = true;
135 for (final Object child : (List<?>) obj) {
136 if (first) {
137 first = false;
138 } else {
139 buf.append(',');
140 }
141 buf.append(escapeJson(child));
142 }
143 buf.append(']');
144 } else if (obj instanceof Map<?, ?>) {
145 buf.append('{');
146 boolean first = true;
147 for (final Map.Entry<?, ?> entry : ((Map<?, ?>) obj).entrySet()) {
148 if (first) {
149 first = false;
150 } else {
151 buf.append(',');
152 }
153 buf.append(escapeJson(entry.getKey())).append(':').append(escapeJson(entry.getValue()));
154 }
155 buf.append('}');
156 } else if ((obj instanceof Integer) || (obj instanceof Long) || (obj instanceof Float) || (obj instanceof Double)) {
157 buf.append((obj));
158 } else if (obj instanceof Boolean) {
159 buf.append(obj.toString());
160 } else if (obj instanceof Date) {
161 final SimpleDateFormat sdf = new SimpleDateFormat(CoreLibConstants.DATE_FORMAT_ISO_8601_EXTEND, Locale.ROOT);
162 buf.append('\"').append(StringEscapeUtils.escapeJson(sdf.format(obj))).append('\"');
163 } else {
164 buf.append('\"').append(StringEscapeUtils.escapeJson(obj.toString())).append('\"');
165 }
166 return buf.toString();
167 }
168
169 public void setMimeType(final String mimeType) {
170 this.mimeType = mimeType;
171 }
172
173 }