1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.api.json;
17
18 import java.io.IOException;
19 import java.net.URLDecoder;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.Map;
26
27 import javax.servlet.FilterChain;
28 import javax.servlet.ServletException;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.codelibs.core.lang.StringUtil;
33 import org.codelibs.fess.Constants;
34 import org.codelibs.fess.api.BaseJsonApiManager;
35 import org.codelibs.fess.app.service.FavoriteLogService;
36 import org.codelibs.fess.app.service.SearchService;
37 import org.codelibs.fess.entity.FacetInfo;
38 import org.codelibs.fess.entity.GeoInfo;
39 import org.codelibs.fess.entity.PingResponse;
40 import org.codelibs.fess.entity.SearchRenderData;
41 import org.codelibs.fess.entity.SearchRequestParams;
42 import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
43 import org.codelibs.fess.es.client.FessEsClient;
44 import org.codelibs.fess.exception.WebApiException;
45 import org.codelibs.fess.helper.LabelTypeHelper;
46 import org.codelibs.fess.helper.PopularWordHelper;
47 import org.codelibs.fess.helper.RelatedContentHelper;
48 import org.codelibs.fess.helper.RelatedQueryHelper;
49 import org.codelibs.fess.helper.SystemHelper;
50 import org.codelibs.fess.helper.UserInfoHelper;
51 import org.codelibs.fess.mylasta.direction.FessConfig;
52 import org.codelibs.fess.util.ComponentUtil;
53 import org.codelibs.fess.util.DocumentUtil;
54 import org.codelibs.fess.util.FacetResponse;
55 import org.codelibs.fess.util.FacetResponse.Field;
56 import org.dbflute.optional.OptionalThing;
57 import org.elasticsearch.common.xcontent.ToXContent;
58 import org.elasticsearch.common.xcontent.XContentBuilder;
59 import org.elasticsearch.common.xcontent.XContentFactory;
60 import org.elasticsearch.script.Script;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 public class JsonApiManager extends BaseJsonApiManager {
65
66 private static final Logger logger = LoggerFactory.getLogger(JsonApiManager.class);
67
68 public JsonApiManager() {
69 setPathPrefix("/json");
70 }
71
72 @Override
73 public boolean matches(final HttpServletRequest request) {
74 if (!ComponentUtil.getFessConfig().isWebApiJson()) {
75 return false;
76 }
77
78 final String servletPath = request.getServletPath();
79 return servletPath.startsWith(pathPrefix);
80 }
81
82 @Override
83 public void process(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException,
84 ServletException {
85 final String formatType = request.getParameter("type");
86 switch (getFormatType(formatType)) {
87 case SEARCH:
88 processSearchRequest(request, response, chain);
89 break;
90 case LABEL:
91 processLabelRequest(request, response, chain);
92 break;
93 case POPULARWORD:
94 processPopularWordRequest(request, response, chain);
95 break;
96 case FAVORITE:
97 processFavoriteRequest(request, response, chain);
98 break;
99 case FAVORITES:
100 processFavoritesRequest(request, response, chain);
101 break;
102 case PING:
103 processPingRequest(request, response, chain);
104 break;
105 default:
106 writeJsonResponse(99, StringUtil.EMPTY, "Not found.");
107 break;
108 }
109 }
110
111 protected void processPingRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
112 final FessEsClient fessEsClient = ComponentUtil.getFessEsClient();
113 int status;
114 Exception err = null;
115 try {
116 final PingResponse pingResponse = fessEsClient.ping();
117 status = pingResponse.getStatus();
118 writeJsonResponse(status, "\"message\":" + pingResponse.getMessage());
119 } catch (final Exception e) {
120 status = 9;
121 err = e;
122 if (logger.isDebugEnabled()) {
123 logger.debug("Failed to process a ping request.", e);
124 }
125 writeJsonResponse(status, null, err);
126 }
127 }
128
129 protected void processSearchRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
130 final SearchService searchService = ComponentUtil.getComponent(SearchService.class);
131 final FessConfig fessConfig = ComponentUtil.getFessConfig();
132 final RelatedQueryHelper relatedQueryHelper = ComponentUtil.getRelatedQueryHelper();
133 final RelatedContentHelper relatedContentHelper = ComponentUtil.getRelatedContentHelper();
134
135 int status = 0;
136 Exception err = null;
137 String query = null;
138 final StringBuilder buf = new StringBuilder(1000);
139 request.setAttribute(Constants.SEARCH_LOG_ACCESS_TYPE, Constants.SEARCH_LOG_ACCESS_TYPE_JSON);
140 try {
141 final SearchRenderData data = new SearchRenderData();
142 final JsonRequestParams params = new JsonRequestParams(request, fessConfig);
143 query = params.getQuery();
144 searchService.search(params, data, OptionalThing.empty());
145 final String execTime = data.getExecTime();
146 final String queryTime = Long.toString(data.getQueryTime());
147 final String pageSize = Integer.toString(data.getPageSize());
148 final String currentPageNumber = Integer.toString(data.getCurrentPageNumber());
149 final String allRecordCount = Long.toString(data.getAllRecordCount());
150 final String allPageCount = Integer.toString(data.getAllPageCount());
151 final List<Map<String, Object>> documentItems = data.getDocumentItems();
152 final FacetResponse facetResponse = data.getFacetResponse();
153 final String queryId = data.getQueryId();
154 final String highlightParams = data.getAppendHighlightParams();
155 final boolean nextPage = data.isExistNextPage();
156 final boolean prevPage = data.isExistPrevPage();
157 final long startRecordNumber = data.getCurrentStartRecordNumber();
158 final long endRecordNumber = data.getCurrentEndRecordNumber();
159 final List<String> pageNumbers = data.getPageNumberList();
160 final boolean partial = data.isPartialResults();
161 final String searchQuery = data.getSearchQuery();
162 final long requestedTime = data.getRequestedTime();
163
164 buf.append("\"q\":");
165 buf.append(escapeJson(query));
166 buf.append(",\"query_id\":");
167 buf.append(escapeJson(queryId));
168 buf.append(",\"exec_time\":");
169 buf.append(execTime);
170 buf.append(",\"query_time\":");
171 buf.append(queryTime);
172 buf.append(',');
173 buf.append("\"page_size\":");
174 buf.append(pageSize);
175 buf.append(',');
176 buf.append("\"page_number\":");
177 buf.append(currentPageNumber);
178 buf.append(',');
179 buf.append("\"record_count\":");
180 buf.append(allRecordCount);
181 buf.append(',');
182 buf.append("\"page_count\":");
183 buf.append(allPageCount);
184 buf.append(",\"highlight_params\":");
185 buf.append(escapeJson(highlightParams));
186 buf.append(",\"next_page\":");
187 buf.append(escapeJson(nextPage));
188 buf.append(",\"prev_page\":");
189 buf.append(escapeJson(prevPage));
190 buf.append(",\"start_record_number\":");
191 buf.append(startRecordNumber);
192 buf.append(",\"end_record_number\":");
193 buf.append(escapeJson(endRecordNumber));
194 buf.append(",\"page_numbers\":");
195 buf.append(escapeJson(pageNumbers));
196 buf.append(",\"partial\":");
197 buf.append(escapeJson(partial));
198 buf.append(",\"search_query\":");
199 buf.append(escapeJson(searchQuery));
200 buf.append(",\"requested_time\":");
201 buf.append(requestedTime);
202 final String[] relatedQueries = relatedQueryHelper.getRelatedQueries(params.getQuery());
203 if (relatedQueries.length > 0) {
204 buf.append(",\"related_query\":");
205 buf.append(escapeJson(relatedQueries));
206 }
207 final String relatedContent = relatedContentHelper.getRelatedContent(params.getQuery());
208 if (StringUtil.isNotBlank(relatedContent)) {
209 buf.append(",\"related_content\":");
210 buf.append(escapeJson(relatedContent));
211 }
212 if (!documentItems.isEmpty()) {
213 buf.append(',');
214 buf.append("\"result\":[");
215 boolean first1 = true;
216 for (final Map<String, Object> document : documentItems) {
217 if (!first1) {
218 buf.append(',');
219 } else {
220 first1 = false;
221 }
222 buf.append('{');
223 boolean first2 = true;
224 for (final Map.Entry<String, Object> entry : document.entrySet()) {
225 final String name = entry.getKey();
226 if (StringUtil.isNotBlank(name) && entry.getValue() != null
227 && ComponentUtil.getQueryHelper().isApiResponseField(name)) {
228 if (!first2) {
229 buf.append(',');
230 } else {
231 first2 = false;
232 }
233 buf.append(escapeJson(name));
234 buf.append(':');
235 buf.append(escapeJson(entry.getValue()));
236 }
237 }
238 buf.append('}');
239 }
240 buf.append(']');
241 }
242 if (facetResponse != null && facetResponse.hasFacetResponse()) {
243
244 if (facetResponse.getFieldList() != null) {
245 buf.append(',');
246 buf.append("\"facet_field\":[");
247 boolean first1 = true;
248 for (final Field field : facetResponse.getFieldList()) {
249 if (!first1) {
250 buf.append(',');
251 } else {
252 first1 = false;
253 }
254 buf.append("{\"name\":");
255 buf.append(escapeJson(field.getName()));
256 buf.append(",\"result\":[");
257 boolean first2 = true;
258 for (final Map.Entry<String, Long> entry : field.getValueCountMap().entrySet()) {
259 if (!first2) {
260 buf.append(',');
261 } else {
262 first2 = false;
263 }
264 buf.append("{\"value\":");
265 buf.append(escapeJson(entry.getKey()));
266 buf.append(",\"count\":");
267 buf.append(entry.getValue());
268 buf.append('}');
269 }
270 buf.append(']');
271 buf.append('}');
272 }
273 buf.append(']');
274 }
275
276 if (facetResponse.getQueryCountMap() != null) {
277 buf.append(',');
278 buf.append("\"facet_query\":[");
279 boolean first1 = true;
280 for (final Map.Entry<String, Long> entry : facetResponse.getQueryCountMap().entrySet()) {
281 if (!first1) {
282 buf.append(',');
283 } else {
284 first1 = false;
285 }
286 buf.append("{\"value\":");
287 buf.append(escapeJson(entry.getKey()));
288 buf.append(",\"count\":");
289 buf.append(entry.getValue());
290 buf.append('}');
291 }
292 buf.append(']');
293 }
294 }
295 } catch (final Exception e) {
296 status = 1;
297 err = e;
298 if (logger.isDebugEnabled()) {
299 logger.debug("Failed to process a search request.", e);
300 }
301 }
302
303 writeJsonResponse(status, buf.toString(), err);
304
305 }
306
307 protected String toGeoRequestString(final GeoInfo geoInfo) {
308 try {
309 final XContentBuilder builder = XContentFactory.jsonBuilder();
310 return geoInfo.toQueryBuilder().toXContent(builder, ToXContent.EMPTY_PARAMS).string();
311 } catch (final Exception e) {
312 return "{\"error\":\"" + detailedMessage(e) + "\"}";
313 }
314 }
315
316 protected String detailedMessage(final Throwable t) {
317 if (t == null) {
318 return "Unknown";
319 }
320 Throwable target = t;
321 if (target.getCause() != null) {
322 final StringBuilder sb = new StringBuilder();
323 while (target != null) {
324 sb.append(target.getClass().getSimpleName());
325 if (target.getMessage() != null) {
326 sb.append("[");
327 sb.append(target.getMessage());
328 sb.append("]");
329 }
330 sb.append("; ");
331 target = target.getCause();
332 if (target != null) {
333 sb.append("nested: ");
334 }
335 }
336 return sb.toString();
337 } else {
338 return target.getClass().getSimpleName() + "[" + target.getMessage() + "]";
339 }
340 }
341
342 protected void processLabelRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
343 final LabelTypeHelper labelTypeHelper = ComponentUtil.getLabelTypeHelper();
344
345 int status = 0;
346 Exception err = null;
347 final StringBuilder buf = new StringBuilder(255);
348 try {
349 final List<Map<String, String>> labelTypeItems = labelTypeHelper.getLabelTypeItemList(SearchRequestType.JSON);
350 buf.append("\"record_count\":");
351 buf.append(labelTypeItems.size());
352 if (!labelTypeItems.isEmpty()) {
353 buf.append(',');
354 buf.append("\"result\":[");
355 boolean first1 = true;
356 for (final Map<String, String> labelMap : labelTypeItems) {
357 if (!first1) {
358 buf.append(',');
359 } else {
360 first1 = false;
361 }
362 buf.append("{\"label\":");
363 buf.append(escapeJson(labelMap.get(Constants.ITEM_LABEL)));
364 buf.append(", \"value\":");
365 buf.append(escapeJson(labelMap.get(Constants.ITEM_VALUE)));
366 buf.append('}');
367 }
368 buf.append(']');
369 }
370 } catch (final Exception e) {
371 status = 1;
372 err = e;
373 if (logger.isDebugEnabled()) {
374 logger.debug("Failed to process a label request.", e);
375 }
376 }
377
378 writeJsonResponse(status, buf.toString(), err);
379
380 }
381
382 protected void processPopularWordRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
383 if (!ComponentUtil.getFessConfig().isWebApiPopularWord()) {
384 writeJsonResponse(9, null, "Unsupported operation.");
385 return;
386 }
387
388 final String seed = request.getParameter("seed");
389 final List<String> tagList = new ArrayList<>();
390 final String[] tags = request.getParameterValues("labels");
391 if (tags != null) {
392 tagList.addAll(Arrays.asList(tags));
393 }
394 final String key = ComponentUtil.getFessConfig().getVirtualHostKey();
395 if (StringUtil.isNotBlank(key)) {
396 tagList.add(key);
397 }
398 final String[] fields = request.getParameterValues("fields");
399 final String[] excludes = StringUtil.EMPTY_STRINGS;
400
401 final PopularWordHelper popularWordHelper = ComponentUtil.getPopularWordHelper();
402
403 int status = 0;
404 Exception err = null;
405 final StringBuilder buf = new StringBuilder(255);
406 try {
407 final List<String> popularWordList =
408 popularWordHelper.getWordList(SearchRequestType.JSON, seed, tagList.toArray(new String[tagList.size()]), null, fields,
409 excludes);
410
411 buf.append("\"result\":[");
412 boolean first1 = true;
413 for (final String word : popularWordList) {
414 if (!first1) {
415 buf.append(',');
416 } else {
417 first1 = false;
418 }
419 buf.append(escapeJson(word));
420 }
421 buf.append(']');
422 } catch (final Exception e) {
423 if (e instanceof WebApiException) {
424 status = ((WebApiException) e).getStatusCode();
425 } else {
426 status = 1;
427 }
428 err = e;
429 if (logger.isDebugEnabled()) {
430 logger.debug("Failed to process a popularWord request.", e);
431 }
432 }
433
434 writeJsonResponse(status, buf.toString(), err);
435
436 }
437
438 protected void processFavoriteRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
439 if (!ComponentUtil.getFessConfig().isUserFavorite()) {
440 writeJsonResponse(9, null, "Unsupported operation.");
441 return;
442 }
443
444 final FessConfig fessConfig = ComponentUtil.getFessConfig();
445 final UserInfoHelper userInfoHelper = ComponentUtil.getUserInfoHelper();
446 final SearchService searchService = ComponentUtil.getComponent(SearchService.class);
447 final FavoriteLogService favoriteLogService = ComponentUtil.getComponent(FavoriteLogService.class);
448 final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
449
450 try {
451 final String docId = request.getParameter("docId");
452 final String queryId = request.getParameter("queryId");
453
454 final String[] docIds = userInfoHelper.getResultDocIds(URLDecoder.decode(queryId, Constants.UTF_8));
455 if (docIds == null) {
456 throw new WebApiException(6, "No searched urls.");
457 }
458
459 searchService.getDocumentByDocId(docId, new String[] { fessConfig.getIndexFieldUrl() }, OptionalThing.empty())
460 .ifPresent(doc -> {
461 final String favoriteUrl = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
462 final String userCode = userInfoHelper.getUserCode();
463
464 if (StringUtil.isBlank(userCode)) {
465 throw new WebApiException(2, "No user session.");
466 } else if (StringUtil.isBlank(favoriteUrl)) {
467 throw new WebApiException(2, "URL is null.");
468 }
469
470 boolean found = false;
471 for (final String id : docIds) {
472 if (docId.equals(id)) {
473 found = true;
474 break;
475 }
476 }
477 if (!found) {
478 throw new WebApiException(5, "Not found: " + favoriteUrl);
479 }
480
481 if (!favoriteLogService.addUrl(userCode, (userInfo, favoriteLog) -> {
482 favoriteLog.setUserInfoId(userInfo.getId());
483 favoriteLog.setUrl(favoriteUrl);
484 favoriteLog.setDocId(docId);
485 favoriteLog.setQueryId(queryId);
486 favoriteLog.setCreatedAt(systemHelper.getCurrentTimeAsLocalDateTime());
487 })) {
488 throw new WebApiException(4, "Failed to add url: " + favoriteUrl);
489 }
490
491 final String id = DocumentUtil.getValue(doc, fessConfig.getIndexFieldId(), String.class);
492 searchService.update(id, builder -> {
493 final Script script = new Script("ctx._source." + fessConfig.getIndexFieldFavoriteCount() + "+=1");
494 builder.setScript(script);
495 final Map<String, Object> upsertMap = new HashMap<>();
496 upsertMap.put(fessConfig.getIndexFieldFavoriteCount(), 1);
497 builder.setUpsert(upsertMap);
498 builder.setRefreshPolicy(Constants.TRUE);
499 });
500
501 writeJsonResponse(0, "\"result\":\"ok\"", (String) null);
502
503 }).orElse(() -> {
504 throw new WebApiException(6, "Not found: " + docId);
505 });
506
507 } catch (final Exception e) {
508 int status;
509 if (e instanceof WebApiException) {
510 status = ((WebApiException) e).getStatusCode();
511 } else {
512 status = 1;
513 }
514 writeJsonResponse(status, null, e);
515 if (logger.isDebugEnabled()) {
516 logger.debug("Failed to process a favorite request.", e);
517 }
518 }
519
520 }
521
522 protected void processFavoritesRequest(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
523 if (!ComponentUtil.getFessConfig().isUserFavorite()) {
524 writeJsonResponse(9, null, "Unsupported operation.");
525 return;
526 }
527
528 final UserInfoHelper userInfoHelper = ComponentUtil.getUserInfoHelper();
529 final FessConfig fessConfig = ComponentUtil.getFessConfig();
530 final SearchService searchService = ComponentUtil.getComponent(SearchService.class);
531 final FavoriteLogService favoriteLogService = ComponentUtil.getComponent(FavoriteLogService.class);
532
533 int status = 0;
534 String body = null;
535 Exception err = null;
536
537 try {
538 final String queryId = request.getParameter("queryId");
539 final String userCode = userInfoHelper.getUserCode();
540
541 if (StringUtil.isBlank(userCode)) {
542 throw new WebApiException(2, "No user session.");
543 } else if (StringUtil.isBlank(queryId)) {
544 throw new WebApiException(3, "Query ID is null.");
545 }
546
547 final String[] docIds = userInfoHelper.getResultDocIds(queryId);
548 final List<Map<String, Object>> docList =
549 searchService.getDocumentListByDocIds(
550 docIds,
551 new String[] { fessConfig.getIndexFieldUrl(), fessConfig.getIndexFieldDocId(),
552 fessConfig.getIndexFieldFavoriteCount() }, OptionalThing.empty(), SearchRequestType.JSON);
553 List<String> urlList = new ArrayList<>(docList.size());
554 for (final Map<String, Object> doc : docList) {
555 final String urlObj = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
556 if (urlObj != null) {
557 urlList.add(urlObj);
558 }
559 }
560 urlList = favoriteLogService.getUrlList(userCode, urlList);
561 final List<String> docIdList = new ArrayList<>(urlList.size());
562 for (final Map<String, Object> doc : docList) {
563 final String urlObj = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
564 if (urlObj != null && urlList.contains(urlObj)) {
565 final String docIdObj = DocumentUtil.getValue(doc, fessConfig.getIndexFieldDocId(), String.class);
566 if (docIdObj != null) {
567 docIdList.add(docIdObj);
568 }
569 }
570 }
571
572 final StringBuilder buf = new StringBuilder(255);
573 buf.append("\"num\":").append(docIdList.size());
574 if (!docIdList.isEmpty()) {
575 buf.append(", \"doc_ids\":[");
576 for (int i = 0; i < docIdList.size(); i++) {
577 if (i > 0) {
578 buf.append(',');
579 }
580 buf.append(escapeJson(docIdList.get(i)));
581 }
582 buf.append(']');
583 }
584 body = buf.toString();
585 } catch (final Exception e) {
586 if (e instanceof WebApiException) {
587 status = ((WebApiException) e).getStatusCode();
588 } else {
589 status = 1;
590 }
591
592 err = e;
593 if (logger.isDebugEnabled()) {
594 logger.debug("Failed to process a favorites request.", e);
595 }
596 }
597
598 writeJsonResponse(status, body, err);
599
600 }
601
602 protected static class JsonRequestParams implements SearchRequestParams {
603
604 private final HttpServletRequest request;
605
606 private final FessConfig fessConfig;
607
608 private int startPosition = -1;
609
610 private int pageSize = -1;
611
612 protected JsonRequestParams(final HttpServletRequest request, final FessConfig fessConfig) {
613 this.request = request;
614 this.fessConfig = fessConfig;
615 }
616
617 @Override
618 public String getQuery() {
619 return request.getParameter("q");
620 }
621
622 @Override
623 public String[] getExtraQueries() {
624 return getParamValueArray(request, "ex_q");
625 }
626
627 @Override
628 public Map<String, String[]> getFields() {
629 final Map<String, String[]> fields = new HashMap<>();
630 for (final Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
631 final String key = entry.getKey();
632 if (key.startsWith("fields.")) {
633 final String[] value = simplifyArray(entry.getValue());
634 fields.put(key.substring("fields.".length()), value);
635 }
636 }
637 return fields;
638 }
639
640 @Override
641 public String[] getLanguages() {
642 return getParamValueArray(request, "lang");
643 }
644
645 @Override
646 public GeoInfo getGeoInfo() {
647 return createGeoInfo(request);
648 }
649
650 @Override
651 public FacetInfo getFacetInfo() {
652 return createFacetInfo(request);
653 }
654
655 @Override
656 public String getSort() {
657 return request.getParameter("sort");
658 }
659
660 @Override
661 public int getStartPosition() {
662 if (startPosition != -1) {
663 return startPosition;
664 }
665
666 final String start = request.getParameter("start");
667 if (StringUtil.isBlank(start)) {
668 startPosition = fessConfig.getPagingSearchPageStartAsInteger();
669 } else {
670 try {
671 startPosition = Integer.parseInt(start);
672 } catch (final NumberFormatException e) {
673 startPosition = fessConfig.getPagingSearchPageStartAsInteger();
674 }
675 }
676 return startPosition;
677 }
678
679 @Override
680 public int getPageSize() {
681 if (pageSize != -1) {
682 return pageSize;
683 }
684
685 final String num = request.getParameter("num");
686 if (StringUtil.isBlank(num)) {
687 pageSize = fessConfig.getPagingSearchPageSizeAsInteger();
688 } else {
689 try {
690 pageSize = Integer.parseInt(num);
691 if (pageSize > fessConfig.getPagingSearchPageMaxSizeAsInteger().intValue() || pageSize <= 0) {
692 pageSize = fessConfig.getPagingSearchPageMaxSizeAsInteger();
693 }
694 } catch (final NumberFormatException e) {
695 pageSize = fessConfig.getPagingSearchPageSizeAsInteger();
696 }
697 }
698 return pageSize;
699 }
700
701 @Override
702 public Object getAttribute(final String name) {
703 return request.getAttribute(name);
704 }
705
706 @Override
707 public Locale getLocale() {
708 return Locale.ROOT;
709 }
710
711 @Override
712 public SearchRequestType getType() {
713 return SearchRequestType.JSON;
714 }
715
716 @Override
717 public String getSimilarDocHash() {
718 return request.getParameter("sdh");
719 }
720
721 }
722 }