View Javadoc
1   /*
2    * Copyright 2012-2017 CodeLibs Project and the Others.
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,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
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.lang3.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.lastaflute.web.util.LaRequestUtil;
35  import org.lastaflute.web.util.LaResponseUtil;
36  
37  public abstract class BaseJsonApiManager extends BaseApiManager {
38  
39      protected void writeJsonResponse(final int status, final String body, final Throwable t) {
40          if (t == null) {
41              writeJsonResponse(status, body, (String) null);
42              return;
43          }
44  
45          if (t instanceof InvalidAccessTokenException) {
46              final InvalidAccessTokenException e = (InvalidAccessTokenException) t;
47              final HttpServletResponse response = LaResponseUtil.getResponse();
48              response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
49              response.setHeader("WWW-Authenticate", "Bearer error=\"" + e.getType() + "\"");
50          }
51  
52          final StringBuilder sb = new StringBuilder();
53          if (StringUtil.isBlank(t.getMessage())) {
54              sb.append(t.getClass().getName());
55          } else {
56              sb.append(t.getMessage());
57          }
58          final StringWriter sw = new StringWriter();
59          t.printStackTrace(new PrintWriter(sw));
60          sb.append(" [ ").append(sw.toString()).append(" ]");
61          try {
62              sw.close();
63          } catch (final IOException ignore) {}
64          writeJsonResponse(status, body, sb.toString());
65      }
66  
67      protected void writeJsonResponse(final int status, final String body, final String errMsg) {
68          String content = null;
69          if (status == 0) {
70              if (StringUtil.isNotBlank(body)) {
71                  content = body;
72              }
73          } else {
74              content = "\"message\":" + escapeJson(errMsg);
75          }
76          writeJsonResponse(status, content);
77      }
78  
79      protected void writeJsonResponse(final int status, final String body) {
80          final String callback = LaRequestUtil.getRequest().getParameter("callback");
81          final boolean isJsonp = StringUtil.isNotBlank(callback);
82  
83          final StringBuilder buf = new StringBuilder(1000);
84          if (isJsonp) {
85              buf.append(escapeCallbackName(callback));
86              buf.append('(');
87          }
88          buf.append("{\"response\":");
89          buf.append("{\"version\":");
90          buf.append(Constants.WEB_API_VERSION);
91          buf.append(',');
92          buf.append("\"status\":");
93          buf.append(status);
94          if (StringUtil.isNotBlank(body)) {
95              buf.append(',');
96              buf.append(body);
97          }
98          buf.append('}');
99          buf.append('}');
100         if (isJsonp) {
101             buf.append(')');
102         }
103         write(buf.toString(), "text/javascript+json", Constants.UTF_8);
104 
105     }
106 
107     protected String escapeCallbackName(final String callbackName) {
108         return "/**/" + callbackName.replaceAll("[^0-9a-zA-Z_\\$\\.]", StringUtil.EMPTY);
109     }
110 
111     protected String escapeJson(final Object obj) {
112         if (obj == null) {
113             return "null";
114         }
115 
116         final StringBuilder buf = new StringBuilder(255);
117         if (obj instanceof String[]) {
118             buf.append('[');
119             boolean first = true;
120             for (final Object child : (String[]) obj) {
121                 if (first) {
122                     first = false;
123                 } else {
124                     buf.append(',');
125                 }
126                 buf.append(escapeJson(child));
127             }
128             buf.append(']');
129         } else if (obj instanceof List<?>) {
130             buf.append('[');
131             boolean first = true;
132             for (final Object child : (List<?>) obj) {
133                 if (first) {
134                     first = false;
135                 } else {
136                     buf.append(',');
137                 }
138                 buf.append(escapeJson(child));
139             }
140             buf.append(']');
141         } else if (obj instanceof Map<?, ?>) {
142             buf.append('{');
143             boolean first = true;
144             for (final Map.Entry<?, ?> entry : ((Map<?, ?>) obj).entrySet()) {
145                 if (first) {
146                     first = false;
147                 } else {
148                     buf.append(',');
149                 }
150                 buf.append(escapeJson(entry.getKey())).append(':').append(escapeJson(entry.getValue()));
151             }
152             buf.append('}');
153         } else if (obj instanceof Integer) {
154             buf.append(((Integer) obj).intValue());
155         } else if (obj instanceof Long) {
156             buf.append(((Long) obj).longValue());
157         } else if (obj instanceof Float) {
158             buf.append(((Float) obj).floatValue());
159         } else if (obj instanceof Double) {
160             buf.append(((Double) obj).doubleValue());
161         } else if (obj instanceof Boolean) {
162             buf.append(obj.toString());
163         } else if (obj instanceof Date) {
164             final SimpleDateFormat sdf = new SimpleDateFormat(CoreLibConstants.DATE_FORMAT_ISO_8601_EXTEND, Locale.ROOT);
165             buf.append('\"').append(StringEscapeUtils.escapeJson(sdf.format(obj))).append('\"');
166         } else {
167             buf.append('\"').append(StringEscapeUtils.escapeJson(obj.toString())).append('\"');
168         }
169         return buf.toString();
170     }
171 
172 }