1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.mylasta.direction;
17
18 import static org.codelibs.core.stream.StreamUtil.split;
19 import static org.codelibs.core.stream.StreamUtil.stream;
20
21 import java.net.Authenticator;
22 import java.net.InetSocketAddress;
23 import java.net.PasswordAuthentication;
24 import java.net.Proxy;
25 import java.net.Proxy.Type;
26 import java.net.SocketAddress;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.Date;
31 import java.util.Enumeration;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.concurrent.ConcurrentHashMap;
39 import java.util.regex.Pattern;
40 import java.util.stream.Collectors;
41 import java.util.stream.Stream;
42
43 import javax.naming.directory.Attribute;
44 import javax.naming.directory.BasicAttribute;
45
46 import org.codelibs.core.exception.ClassNotFoundRuntimeException;
47 import org.codelibs.core.lang.StringUtil;
48 import org.codelibs.core.misc.Pair;
49 import org.codelibs.core.misc.Tuple3;
50 import org.codelibs.core.misc.Tuple4;
51 import org.codelibs.fess.Constants;
52 import org.codelibs.fess.helper.PermissionHelper;
53 import org.codelibs.fess.ldap.LdapUtil;
54 import org.codelibs.fess.mylasta.action.FessUserBean;
55 import org.codelibs.fess.taglib.FessFunctions;
56 import org.codelibs.fess.util.ComponentUtil;
57 import org.codelibs.fess.util.JvmUtil;
58 import org.codelibs.fess.util.PrunedTag;
59 import org.dbflute.optional.OptionalThing;
60 import org.dbflute.util.DfTypeUtil;
61 import org.lastaflute.job.LaJob;
62 import org.lastaflute.job.subsidiary.JobConcurrentExec;
63 import org.lastaflute.web.validation.RequiredValidator;
64 import org.lastaflute.web.validation.theme.typed.DoubleTypeValidator;
65 import org.lastaflute.web.validation.theme.typed.FloatTypeValidator;
66 import org.lastaflute.web.validation.theme.typed.IntegerTypeValidator;
67 import org.lastaflute.web.validation.theme.typed.LongTypeValidator;
68 import org.opensearch.search.sort.SortBuilder;
69 import org.opensearch.search.sort.SortBuilders;
70 import org.opensearch.search.sort.SortOrder;
71
72 public interface FessProp {
73
74 String API_PING_SEARCH_ENGINE_FIELD_SET = "apiPingSearchEngineFieldSet";
75
76 String QUERY_HIGHLIGHT_TERMINAL_CHARS = "queryHighlightTerminalChars";
77
78 String QUERY_HIGHLIGHT_BOUNDARY_CHARS = "queryHighlightBoundaryChars";
79
80 String QUERY_TRACK_TOTAL_HITS_VALUE = "queryTrackTotalHitsValue";
81
82 String CORS_ALLOW_ORIGIN = "CorsAllowOrigin";
83
84 String API_DASHBOARD_RESPONSE_HEADER_LIST = "apiDashboardResponseHeaderList";
85
86 String API_JSON_RESPONSE_HEADER_LIST = "apiJsonResponseHeaderList";
87
88 String API_GSA_RESPONSE_HEADER_LIST = "apiGsaResponseHeaderList";
89
90 String SMB_AVAILABLE_SID_TYPES = "smbAvailableSidTypes";
91
92 String LOGGING_SEARCH_DOCS_FIELDS = "loggingSearchDocsFields";
93
94 String API_SEARCH_ACCEPT_REFERERS = "apiSearchAcceptReferers";
95
96 String QUERY_GSA_RESPONSE_FIELDS = "queryGsaResponseFields";
97
98 String THUMBNAIL_HTML_IMAGE_EXCLUDE_EXTENSIONS = "ThumbnailHtmlImageExcludeExtensions";
99
100 String VIRTUAL_HOST_VALUE = "VirtualHostValue";
101
102 String QUERY_DEFAULT_LANGUAGES = "queryDefaultLanguages";
103
104 String HTML_PROXY = "httpProxy";
105
106 String CRAWLER_FAILURE_URL_STATUS_CODES = "crawlerFailureUrlStatusCodes";
107
108 String VIRTUAL_HOST_HEADERS = "virtualHostHeaders";
109
110 String QUERY_COLLAPSE_INNER_HITS_SORTS = "queryCollapseInnerHitsSorts";
111
112 String USER_CODE_PATTERN = "userCodePattern";
113
114 String API_ADMIN_ACCESS_PERMISSION_SET = "apiAdminAccessPermissionSet";
115
116 String CRAWLER_DOCUMENT_SPACE_CHARS = "crawlerDocumentSpaceChars";
117
118 String CRAWLER_DOCUMENT_SPACES = "crawlerDocumentSpaces";
119
120 String CRAWLER_DOCUMENT_FULLSTOP_CHARS = "crawlerDocumentFullstopChars";
121
122 String INDEX_ADMIN_ARRAY_FIELD_SET = "indexAdminArrayFieldSet";
123
124 String INDEX_ADMIN_DATE_FIELD_SET = "indexAdminDateFieldSet";
125
126 String INDEX_ADMIN_INTEGER_FIELD_SET = "indexAdminIntegerFieldSet";
127
128 String INDEX_ADMIN_LONG_FIELD_SET = "indexAdminLongFieldSet";
129
130 String INDEX_ADMIN_FLOAT_FIELD_SET = "indexAdminFloatFieldSet";
131
132 String INDEX_ADMIN_DOUBLE_FIELD_SET = "indexAdminDoubleFieldSet";
133
134 String AUTHENTICATION_ADMIN_ROLES = "authenticationAdminRoles";
135
136 String SEARCH_GUEST_ROLE_LIST = "searchGuestPermissionList";
137
138 String SUGGEST_SEARCH_LOG_PERMISSIONS = "suggestSearchLogPermissions";
139
140 String GROUP_VALUE_PREFIX = "group:";
141
142 String ROLE_VALUE_PREFIX = "role:";
143
144 String APP_VALUES = "appValues";
145
146 String DEFAULT_SORT_VALUES = "defaultSortValues";
147
148 String DEFAULT_LABEL_VALUES = "defaultLabelValues";
149
150 String VIRTUAL_HOST_VALUES = "virtualHostValues";
151
152 String QUERY_LANGUAGE_MAPPING = "queryLanguageMapping";
153
154 String CRAWLER_METADATA_NAME_MAPPING = "crawlerMetadataNameMapping";
155
156 String CRAWLER_METADATA_CONTENT_EXCLUDES = "crawlerMetadataContentExcludes";
157
158 Map<String, Object> propMap = new ConcurrentHashMap<>();
159
160 String getOrDefault(String propertyKey, String defaultValue);
161
162
163
164
165
166 default void storeSystemProperties() {
167 ComponentUtil.getSystemProperties().store();
168 }
169
170 default String getSystemProperty(final String key) {
171 return ComponentUtil.getSystemProperties().getProperty(key, System.getProperty(Constants.SYSTEM_PROP_PREFIX + key));
172 }
173
174 default String getSystemProperty(final String key, final String defaultValue) {
175 return ComponentUtil.getSystemProperties().getProperty(key, System.getProperty(Constants.SYSTEM_PROP_PREFIX + key, defaultValue));
176 }
177
178 default void setSystemProperty(final String key, final String value) {
179 if (value != null) {
180 ComponentUtil.getSystemProperties().setProperty(key, value);
181 } else {
182 ComponentUtil.getSystemProperties().remove(key);
183 }
184 }
185
186 default boolean getSystemPropertyAsBoolean(final String key, final boolean defaultValue) {
187 return Constants.TRUE.equalsIgnoreCase(getSystemProperty(key, defaultValue ? Constants.TRUE : Constants.FALSE));
188 }
189
190 default void setSystemPropertyAsBoolean(final String key, final boolean value) {
191 setSystemProperty(key, value ? Constants.TRUE : Constants.FALSE);
192 }
193
194 default int getSystemPropertyAsInt(final String key, final int defaultValue) {
195 final String value = getSystemProperty(key);
196 if (value != null) {
197 try {
198 return Integer.parseInt(value);
199 } catch (final NumberFormatException e) {
200
201 }
202 }
203 return defaultValue;
204 }
205
206 default void setSystemPropertyAsInt(final String key, final int value) {
207 setSystemProperty(key, Integer.toString(value));
208 }
209
210 default void setSearchFileProxy(final boolean value) {
211 setSystemPropertyAsBoolean(Constants.SEARCH_FILE_PROXY_PROPERTY, value);
212 }
213
214 default boolean isSearchFileProxyEnabled() {
215 return getSystemPropertyAsBoolean(Constants.SEARCH_FILE_PROXY_PROPERTY, true);
216 }
217
218 default void setUseBrowserLocaleForSearch(final boolean value) {
219 setSystemPropertyAsBoolean(Constants.USE_BROWSER_LOCALE_FOR_SEARCH_PROPERTY, value);
220 }
221
222 default boolean isBrowserLocaleForSearchUsed() {
223 return getSystemPropertyAsBoolean(Constants.USE_BROWSER_LOCALE_FOR_SEARCH_PROPERTY, false);
224 }
225
226 default String[] getDefaultSortValues(final OptionalThing<FessUserBean> userBean) {
227 @SuppressWarnings("unchecked")
228 List<Pair<String, String>> list = (List<Pair<String, String>>) propMap.get(DEFAULT_SORT_VALUES);
229 if (list == null) {
230 final String value = getSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY);
231 if (StringUtil.isBlank(value)) {
232 list = Collections.emptyList();
233 } else {
234 final Set<String> keySet = new HashSet<>();
235 list = split(value, "\n").get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> {
236 final String[] pair = s.split("=");
237 if (pair.length == 1) {
238 return new Pair<>(StringUtil.EMPTY, pair[0].trim());
239 }
240 if (pair.length == 2) {
241 String sortValue = pair[1].trim();
242 if (StringUtil.isBlank(sortValue) || "score".equals(sortValue)) {
243 sortValue = "score.desc";
244 }
245 return new Pair<>(pair[0].trim(), sortValue);
246 }
247 return null;
248 }).filter(o -> o != null && keySet.add(o.getFirst())).collect(Collectors.toList()));
249 }
250 propMap.put(DEFAULT_SORT_VALUES, list);
251 }
252 return list.stream().map(p -> {
253 final String key = p.getFirst();
254 if (StringUtil.isEmpty(key) || userBean
255 .map(user -> stream(user.getRoles()).get(stream -> stream.anyMatch(s -> (ROLE_VALUE_PREFIX + s).equals(key)))
256 || stream(user.getGroups()).get(stream -> stream.anyMatch(s -> (GROUP_VALUE_PREFIX + s).equals(key))))
257 .orElse(false)) {
258 return p.getSecond();
259 }
260 return null;
261 }).filter(StringUtil::isNotBlank).toArray(n -> new String[n]);
262 }
263
264 default void setDefaultSortValue(final String value) {
265 setSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY, value);
266 propMap.remove(DEFAULT_SORT_VALUES);
267 }
268
269 default String getDefaultSortValue() {
270 return getSystemProperty(Constants.DEFAULT_SORT_VALUE_PROPERTY, StringUtil.EMPTY);
271 }
272
273 default String[] getDefaultLabelValues(final OptionalThing<FessUserBean> userBean) {
274 @SuppressWarnings("unchecked")
275 Map<String, List<String>> map = (Map<String, List<String>>) propMap.get(DEFAULT_LABEL_VALUES);
276 if (map == null) {
277 final String value = getSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY);
278 if (StringUtil.isBlank(value)) {
279 map = Collections.emptyMap();
280 } else {
281 final Set<String> keySet = new HashSet<>();
282 map = split(value, "\n").get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> {
283 final String[] pair = s.split("=");
284 if (pair.length == 1) {
285 return new Pair<>(StringUtil.EMPTY, pair[0].trim());
286 }
287 if (pair.length == 2) {
288 return new Pair<>(pair[0].trim(), pair[1].trim());
289 }
290 return null;
291 })
292 .filter(o -> o != null && keySet.add(o.getFirst()))
293 .collect(HashMap<String, List<String>>::new, (m, d) -> m.put(d.getFirst(), Arrays.asList(d.getSecond().split(","))),
294 HashMap::putAll));
295 }
296 propMap.put(DEFAULT_LABEL_VALUES, map);
297 }
298 return map.entrySet().stream().flatMap(e -> {
299 final String key = e.getKey();
300 if (StringUtil.isEmpty(key) || userBean
301 .map(user -> stream(user.getRoles()).get(stream -> stream.anyMatch(s -> (ROLE_VALUE_PREFIX + s).equals(key)))
302 || stream(user.getGroups()).get(stream -> stream.anyMatch(s -> (GROUP_VALUE_PREFIX + s).equals(key))))
303 .orElse(false)) {
304 return e.getValue().stream();
305 }
306 return Stream.empty();
307 }).filter(StringUtil::isNotBlank).toArray(n -> new String[n]);
308 }
309
310 default void setAppValue(final String value) {
311 setSystemProperty(Constants.APP_VALUE_PROPERTY, value);
312 propMap.remove(APP_VALUES);
313 }
314
315 default String getAppValue() {
316 return getSystemProperty(Constants.APP_VALUE_PROPERTY, StringUtil.EMPTY);
317 }
318
319 default void setDefaultLabelValue(final String value) {
320 setSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, value);
321 propMap.remove(DEFAULT_LABEL_VALUES);
322 }
323
324 default String getDefaultLabelValue() {
325 return getSystemProperty(Constants.DEFAULT_LABEL_VALUE_PROPERTY, StringUtil.EMPTY);
326 }
327
328 default void setVirtualHostValue(final String value) {
329 setSystemProperty(Constants.VIRTUAL_HOST_VALUE_PROPERTY, value);
330 propMap.remove(VIRTUAL_HOST_HEADERS);
331 }
332
333 default String getVirtualHostValue() {
334 return getSystemProperty(Constants.VIRTUAL_HOST_VALUE_PROPERTY, getVirtualHostHeaders());
335 }
336
337 default void setLoginRequired(final boolean value) {
338 setSystemPropertyAsBoolean(Constants.LOGIN_REQUIRED_PROPERTY, value);
339 }
340
341 default boolean isLoginRequired() {
342 return getSystemPropertyAsBoolean(Constants.LOGIN_REQUIRED_PROPERTY, false);
343 }
344
345 default void setResultCollapsed(final boolean value) {
346 setSystemPropertyAsBoolean(Constants.RESULT_COLLAPSED_PROPERTY, value);
347 }
348
349 default boolean isResultCollapsed() {
350 return switch (getFesenType()) {
351 case Constants.FESEN_TYPE_CLOUD, Constants.FESEN_TYPE_AWS -> false;
352 default -> getSystemPropertyAsBoolean(Constants.RESULT_COLLAPSED_PROPERTY, false);
353 };
354 }
355
356 default void setLoginLinkEnabled(final boolean value) {
357 setSystemPropertyAsBoolean(Constants.LOGIN_LINK_ENALBED_PROPERTY, value);
358 }
359
360 default boolean isLoginLinkEnabled() {
361 return getSystemPropertyAsBoolean(Constants.LOGIN_LINK_ENALBED_PROPERTY, true);
362 }
363
364 default void setThumbnailEnabled(final boolean value) {
365 setSystemPropertyAsBoolean(Constants.THUMBNAIL_ENALBED_PROPERTY, value);
366 }
367
368 default boolean isThumbnailEnabled() {
369 return getSystemPropertyAsBoolean(Constants.THUMBNAIL_ENALBED_PROPERTY, false);
370 }
371
372 default void setIncrementalCrawling(final boolean value) {
373 setSystemPropertyAsBoolean(Constants.INCREMENTAL_CRAWLING_PROPERTY, value);
374 }
375
376 default boolean isIncrementalCrawling() {
377 return getSystemPropertyAsBoolean(Constants.INCREMENTAL_CRAWLING_PROPERTY, true);
378 }
379
380 default void setDayForCleanup(final int value) {
381 setSystemPropertyAsInt(Constants.DAY_FOR_CLEANUP_PROPERTY, value);
382 }
383
384 default int getDayForCleanup() {
385 return getSystemPropertyAsInt(Constants.DAY_FOR_CLEANUP_PROPERTY, Constants.DEFAULT_DAY_FOR_CLEANUP);
386 }
387
388 default void setCrawlingThreadCount(final int value) {
389 setSystemPropertyAsInt(Constants.CRAWLING_THREAD_COUNT_PROPERTY, value);
390 }
391
392 default int getCrawlingThreadCount() {
393 return getSystemPropertyAsInt(Constants.CRAWLING_THREAD_COUNT_PROPERTY, 5);
394 }
395
396 default void setSearchLog(final boolean value) {
397 setSystemPropertyAsBoolean(Constants.SEARCH_LOG_PROPERTY, value);
398 }
399
400 default boolean isSearchLog() {
401 return getSystemPropertyAsBoolean(Constants.SEARCH_LOG_PROPERTY, true);
402 }
403
404 default void setUserInfo(final boolean value) {
405 setSystemPropertyAsBoolean(Constants.USER_INFO_PROPERTY, value);
406 }
407
408 default boolean isUserInfo() {
409 return getSystemPropertyAsBoolean(Constants.USER_INFO_PROPERTY, true);
410 }
411
412 default void setUserFavorite(final boolean value) {
413 setSystemPropertyAsBoolean(Constants.USER_FAVORITE_PROPERTY, value);
414 }
415
416 default boolean isUserFavorite() {
417 return getSystemPropertyAsBoolean(Constants.USER_FAVORITE_PROPERTY, false);
418 }
419
420 default void setWebApiJson(final boolean value) {
421 setSystemPropertyAsBoolean(Constants.WEB_API_JSON_PROPERTY, value);
422 }
423
424 default boolean isWebApiJson() {
425 return getSystemPropertyAsBoolean(Constants.WEB_API_JSON_PROPERTY, true);
426 }
427
428 default boolean isWebApiGsa() {
429 return getSystemPropertyAsBoolean(Constants.WEB_API_GSA_PROPERTY, false);
430 }
431
432 default void setAppendQueryParameter(final boolean value) {
433 setSystemPropertyAsBoolean(Constants.APPEND_QUERY_PARAMETER_PROPERTY, value);
434 }
435
436 default boolean isAppendQueryParameter() {
437 return getSystemPropertyAsBoolean(Constants.APPEND_QUERY_PARAMETER_PROPERTY, false);
438 }
439
440 default void setIgnoreFailureType(final String value) {
441 setSystemProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, value);
442 }
443
444 default String getIgnoreFailureType() {
445 return getSystemProperty(Constants.IGNORE_FAILURE_TYPE_PROPERTY, Constants.DEFAULT_IGNORE_FAILURE_TYPE);
446 }
447
448 default void setFailureCountThreshold(final int value) {
449 setSystemPropertyAsInt(Constants.FAILURE_COUNT_THRESHOLD_PROPERTY, value);
450 }
451
452 default int getFailureCountThreshold() {
453 return getSystemPropertyAsInt(Constants.FAILURE_COUNT_THRESHOLD_PROPERTY, Constants.DEFAULT_FAILURE_COUNT);
454 }
455
456 default void setWebApiPopularWord(final boolean value) {
457 setSystemPropertyAsBoolean(Constants.WEB_API_POPULAR_WORD_PROPERTY, value);
458 }
459
460 default boolean isWebApiPopularWord() {
461 return getSystemPropertyAsBoolean(Constants.WEB_API_POPULAR_WORD_PROPERTY, true);
462 }
463
464 default void setCsvFileEncoding(final String value) {
465 setSystemProperty(Constants.CSV_FILE_ENCODING_PROPERTY, value);
466 }
467
468 default String getCsvFileEncoding() {
469 return getSystemProperty(Constants.CSV_FILE_ENCODING_PROPERTY, Constants.UTF_8);
470 }
471
472 default void setPurgeSearchLogDay(final int value) {
473 setSystemPropertyAsInt(Constants.PURGE_SEARCH_LOG_DAY_PROPERTY, value);
474 }
475
476 default int getPurgeSearchLogDay() {
477 return getSystemPropertyAsInt(Constants.PURGE_SEARCH_LOG_DAY_PROPERTY, DfTypeUtil.toInteger(Constants.DEFAULT_PURGE_DAY));
478 }
479
480 default void setPurgeJobLogDay(final int value) {
481 setSystemPropertyAsInt(Constants.PURGE_JOB_LOG_DAY_PROPERTY, value);
482 }
483
484 default int getPurgeJobLogDay() {
485 return getSystemPropertyAsInt(Constants.PURGE_JOB_LOG_DAY_PROPERTY, DfTypeUtil.toInteger(Constants.DEFAULT_PURGE_DAY));
486 }
487
488 default void setPurgeUserInfoDay(final int value) {
489 setSystemPropertyAsInt(Constants.PURGE_USER_INFO_DAY_PROPERTY, value);
490 }
491
492 default int getPurgeUserInfoDay() {
493 return getSystemPropertyAsInt(Constants.PURGE_USER_INFO_DAY_PROPERTY, DfTypeUtil.toInteger(Constants.DEFAULT_PURGE_DAY));
494 }
495
496 default void setPurgeByBots(final String value) {
497 setSystemProperty(Constants.PURGE_BY_BOTS_PROPERTY, value);
498 }
499
500 default String getPurgeByBots() {
501 return getSystemProperty(Constants.PURGE_BY_BOTS_PROPERTY, Constants.DEFAULT_PURGE_BY_BOTS);
502 }
503
504 default boolean hasNotification() {
505 return StringUtil.isNotBlank(getNotificationTo()) || StringUtil.isNotBlank(getSlackWebhookUrls())
506 || StringUtil.isNotBlank(getGoogleChatWebhookUrls());
507 }
508
509 default void setSlackWebhookUrls(final String value) {
510 setSystemProperty(Constants.SLACK_WEBHOOK_URLS_PROPERTY, value);
511 }
512
513 default String getSlackWebhookUrls() {
514 return getSystemProperty(Constants.SLACK_WEBHOOK_URLS_PROPERTY, StringUtil.EMPTY);
515 }
516
517 default void setGoogleChatWebhookUrls(final String value) {
518 setSystemProperty(Constants.GOOGLE_CHAT_WEBHOOK_URLS_PROPERTY, value);
519 }
520
521 default String getGoogleChatWebhookUrls() {
522 return getSystemProperty(Constants.GOOGLE_CHAT_WEBHOOK_URLS_PROPERTY, StringUtil.EMPTY);
523 }
524
525 default void setNotificationTo(final String value) {
526 setSystemProperty(Constants.NOTIFICATION_TO_PROPERTY, value);
527 }
528
529 default String getNotificationTo() {
530 return getSystemProperty(Constants.NOTIFICATION_TO_PROPERTY, StringUtil.EMPTY);
531 }
532
533 default void setLogNotificationEnabled(final boolean value) {
534 setSystemPropertyAsBoolean(Constants.LOG_NOTIFICATION_ENABLED_PROPERTY, value);
535 }
536
537 default boolean isLogNotificationEnabled() {
538 return getSystemPropertyAsBoolean(Constants.LOG_NOTIFICATION_ENABLED_PROPERTY, false);
539 }
540
541 default void setLogNotificationLevel(final String value) {
542 setSystemProperty(Constants.LOG_NOTIFICATION_LEVEL_PROPERTY, value);
543 }
544
545 default String getLogNotificationLevel() {
546 return getSystemProperty(Constants.LOG_NOTIFICATION_LEVEL_PROPERTY, "ERROR");
547 }
548
549 default void setSuggestSearchLog(final boolean value) {
550 setSystemPropertyAsBoolean(Constants.SUGGEST_SEARCH_LOG_PROPERTY, value);
551 }
552
553 default boolean isSuggestSearchLog() {
554 return getSystemPropertyAsBoolean(Constants.SUGGEST_SEARCH_LOG_PROPERTY, true);
555 }
556
557 default void setSuggestDocuments(final boolean value) {
558 setSystemPropertyAsBoolean(Constants.SUGGEST_DOCUMENTS_PROPERTY, value);
559 }
560
561 default boolean isSuggestDocuments() {
562 return getSystemPropertyAsBoolean(Constants.SUGGEST_DOCUMENTS_PROPERTY, true);
563 }
564
565 default void setPurgeSuggestSearchLogDay(final int value) {
566 setSystemPropertyAsInt(Constants.PURGE_SUGGEST_SEARCH_LOG_DAY_PROPERTY, value);
567 }
568
569 default int getPurgeSuggestSearchLogDay() {
570 return getSystemPropertyAsInt(Constants.PURGE_SUGGEST_SEARCH_LOG_DAY_PROPERTY,
571 DfTypeUtil.toInteger(Constants.DEFAULT_SUGGEST_PURGE_DAY));
572 }
573
574 default void setLdapInitialContextFactory(final String value) {
575 setSystemProperty(Constants.LDAP_INITIAL_CONTEXT_FACTORY, value);
576 }
577
578 default String getLdapInitialContextFactory() {
579 return getSystemProperty(Constants.LDAP_INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
580 }
581
582 default void setLdapSecurityAuthentication(final String value) {
583 setSystemProperty(Constants.LDAP_SECURITY_AUTHENTICATION, value);
584 }
585
586 default String getLdapSecurityAuthentication() {
587 return getSystemProperty(Constants.LDAP_SECURITY_AUTHENTICATION, "simple");
588 }
589
590 default void setLdapProviderUrl(final String value) {
591 setSystemProperty(Constants.LDAP_PROVIDER_URL, value);
592 }
593
594 default String getLdapProviderUrl() {
595 return getSystemProperty(Constants.LDAP_PROVIDER_URL);
596 }
597
598 default void setLdapSecurityPrincipal(final String value) {
599 setSystemProperty(Constants.LDAP_SECURITY_PRINCIPAL, value);
600 }
601
602 default String getLdapMemberofAttribute() {
603 return getSystemProperty(Constants.LDAP_MEMBEROF_ATTRIBUTE, "memberOf");
604 }
605
606 default void setLdapMemberofAttribute(final String value) {
607 setSystemProperty(Constants.LDAP_MEMBEROF_ATTRIBUTE, value);
608 }
609
610 default void setStorageEndpoint(final String value) {
611 setSystemProperty(Constants.STORAGE_ENDPOINT, value);
612 }
613
614 default String getStorageEndpoint() {
615 return getSystemProperty(Constants.STORAGE_ENDPOINT, StringUtil.EMPTY);
616 }
617
618 default void setStorageAccessKey(final String value) {
619 setSystemProperty(Constants.STORAGE_ACCESS_KEY, value);
620 }
621
622 default String getStorageAccessKey() {
623 return getSystemProperty(Constants.STORAGE_ACCESS_KEY, StringUtil.EMPTY);
624 }
625
626 default void setStorageSecretKey(final String value) {
627 setSystemProperty(Constants.STORAGE_SECRET_KEY, value);
628 }
629
630 default String getStorageSecretKey() {
631 return getSystemProperty(Constants.STORAGE_SECRET_KEY, StringUtil.EMPTY);
632 }
633
634 default void setStorageBucket(final String value) {
635 setSystemProperty(Constants.STORAGE_BUCKET, value);
636 }
637
638 default String getStorageBucket() {
639 return getSystemProperty(Constants.STORAGE_BUCKET, StringUtil.EMPTY);
640 }
641
642 default void setStorageType(final String value) {
643 setSystemProperty(Constants.STORAGE_TYPE, value);
644 }
645
646 default String getStorageType() {
647 return getSystemProperty(Constants.STORAGE_TYPE, "auto");
648 }
649
650 default void setStorageRegion(final String value) {
651 setSystemProperty(Constants.STORAGE_REGION, value);
652 }
653
654 default String getStorageRegion() {
655 return getSystemProperty(Constants.STORAGE_REGION, "us-east-1");
656 }
657
658 default void setStorageProjectId(final String value) {
659 setSystemProperty(Constants.STORAGE_PROJECT_ID, value);
660 }
661
662 default String getStorageProjectId() {
663 return getSystemProperty(Constants.STORAGE_PROJECT_ID, StringUtil.EMPTY);
664 }
665
666 default void setStorageCredentialsPath(final String value) {
667 setSystemProperty(Constants.STORAGE_CREDENTIALS_PATH, value);
668 }
669
670 default String getStorageCredentialsPath() {
671 return getSystemProperty(Constants.STORAGE_CREDENTIALS_PATH, StringUtil.EMPTY);
672 }
673
674 default void setRagLlmName(final String value) {
675 setSystemProperty(Constants.RAG_LLM_NAME, value);
676 }
677
678 default String getRagLlmName() {
679 return getSystemProperty(Constants.RAG_LLM_NAME, "ollama");
680 }
681
682 Integer getLdapMaxUsernameLengthAsInteger();
683
684 default String getLdapSecurityPrincipal(final String username) {
685 final String value;
686 final int maxLength = getLdapMaxUsernameLengthAsInteger();
687 if (username == null) {
688 value = StringUtil.EMPTY;
689 } else if (maxLength >= 0 && username.length() > maxLength) {
690 value = LdapUtil.escapeValue(username.substring(0, maxLength));
691 } else {
692 value = LdapUtil.escapeValue(username);
693 }
694 return String.format(getSystemProperty(Constants.LDAP_SECURITY_PRINCIPAL, StringUtil.EMPTY), value);
695 }
696
697 default String getLdapSecurityPrincipal() {
698 return getSystemProperty(Constants.LDAP_SECURITY_PRINCIPAL);
699 }
700
701 default void setLdapAdminSecurityPrincipal(final String value) {
702 setSystemProperty(Constants.LDAP_ADMIN_SECURITY_PRINCIPAL, value);
703 }
704
705 default String getLdapAdminSecurityPrincipal() {
706 return getSystemProperty(Constants.LDAP_ADMIN_SECURITY_PRINCIPAL);
707 }
708
709 default void setLdapAdminSecurityCredentials(final String value) {
710 setSystemProperty(Constants.LDAP_ADMIN_SECURITY_CREDENTIALS,
711 Constants.CIPHER_PREFIX + ComponentUtil.getPrimaryCipher().encrypt(value));
712 }
713
714 default String getLdapAdminSecurityCredentials() {
715 final String value = getSystemProperty(Constants.LDAP_ADMIN_SECURITY_CREDENTIALS);
716 if (StringUtil.isNotBlank(value) && value.startsWith(Constants.CIPHER_PREFIX)) {
717 return ComponentUtil.getPrimaryCipher().decrypt(value.substring(Constants.CIPHER_PREFIX.length()));
718 }
719 return value;
720 }
721
722 default void setLdapBaseDn(final String value) {
723 setSystemProperty(Constants.LDAP_BASE_DN, value);
724 }
725
726 default String getLdapBaseDn() {
727 return getSystemProperty(Constants.LDAP_BASE_DN);
728 }
729
730 default void setLdapAccountFilter(final String value) {
731 setSystemProperty(Constants.LDAP_ACCOUNT_FILTER, value);
732 }
733
734 default String getLdapAccountFilter() {
735 return getSystemProperty(Constants.LDAP_ACCOUNT_FILTER);
736 }
737
738 default void setLdapGroupFilter(final String value) {
739 setSystemProperty(Constants.LDAP_GROUP_FILTER, value);
740 }
741
742 default String getLdapGroupFilter() {
743 return getSystemProperty(Constants.LDAP_GROUP_FILTER, StringUtil.EMPTY);
744 }
745
746 default void setNotificationLogin(final String value) {
747 setSystemProperty(Constants.NOTIFICATION_LOGIN, value);
748 }
749
750 default String getNotificationLogin() {
751 return getSystemProperty(Constants.NOTIFICATION_LOGIN, StringUtil.EMPTY);
752 }
753
754 default void setNotificationAdvanceSearch(final String value) {
755 setSystemProperty(Constants.NOTIFICATION_ADVANCE_SEARCH, value);
756 }
757
758 default String getNotificationAdvanceSearch() {
759 return getSystemProperty(Constants.NOTIFICATION_ADVANCE_SEARCH, StringUtil.EMPTY);
760 }
761
762 default void setNotificationSearchTop(final String value) {
763 setSystemProperty(Constants.NOTIFICATION_SEARCH_TOP, value);
764 }
765
766 default String getNotificationSearchTop() {
767 return getSystemProperty(Constants.NOTIFICATION_SEARCH_TOP, StringUtil.EMPTY);
768 }
769
770 default void setUserAgentName(final String value) {
771 setSystemProperty(Constants.CRAWLING_USER_AGENT_PROPERTY, value);
772 }
773
774 default String getUserAgentName() {
775 return getSystemProperty(Constants.CRAWLING_USER_AGENT_PROPERTY, Constants.CRAWLING_USER_AGENT_PREFIX
776 + ComponentUtil.getSystemHelper().getProductVersion() + Constants.CRAWLING_USER_AGENT_SUFFIX);
777 }
778
779 default void setLtrModelName(final String value) {
780 setSystemProperty(Constants.LTR_MODEL_NAME_PROPERTY, value);
781 }
782
783 default String getLtrModelName() {
784 return getSystemProperty(Constants.LTR_MODEL_NAME_PROPERTY, StringUtil.EMPTY);
785 }
786
787 default void setLtrWindowSize(final int value) {
788 setSystemPropertyAsInt(Constants.LTR_WINDOW_SIZE_PROPERTY, value);
789 }
790
791 default int getLtrWindowSize() {
792 return getSystemPropertyAsInt(Constants.LTR_WINDOW_SIZE_PROPERTY, 100);
793 }
794
795
796
797
798
799
800 default String[] getEntraIdPermissionFields() {
801 String value = getSystemProperty("entraid.permission.fields", null);
802 if (StringUtil.isBlank(value)) {
803 value = getSystemProperty("aad.permission.fields", "mail");
804 }
805 return split(value, ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).toArray(n -> new String[n]));
806 }
807
808
809
810
811
812
813 default boolean isEntraIdUseDomainServices() {
814 String value = getSystemProperty("entraid.use.ds", null);
815 if (StringUtil.isBlank(value)) {
816 value = getSystemProperty("aad.use.ds", "true");
817 }
818 return Constants.TRUE.equalsIgnoreCase(value);
819 }
820
821 default void setSsoType(final String value) {
822 setSystemProperty(Constants.SSO_TYPE_PROPERTY, value);
823 }
824
825 default String getSsoType() {
826 return getSystemProperty(Constants.SSO_TYPE_PROPERTY, Constants.NONE);
827 }
828
829
830
831
832
833 String getAuthenticationAdminRoles();
834
835 default String[] getAuthenticationAdminRolesAsArray() {
836 String[] roles = (String[]) propMap.get(AUTHENTICATION_ADMIN_ROLES);
837 if (roles == null) {
838 roles = getAuthenticationAdminRoles().split(",");
839 propMap.put(AUTHENTICATION_ADMIN_ROLES, roles);
840 }
841 return roles;
842 }
843
844 String getJvmCrawlerOptions();
845
846 default String[] getJvmCrawlerOptionsAsArray() {
847 return JvmUtil.filterJvmOptions(getJvmCrawlerOptions().split("\n"));
848 }
849
850 String getJvmSuggestOptions();
851
852 default String[] getJvmSuggestOptionsAsArray() {
853 return JvmUtil.filterJvmOptions(getJvmSuggestOptions().split("\n"));
854 }
855
856 String getJvmThumbnailOptions();
857
858 default String[] getJvmThumbnailOptionsAsArray() {
859 return JvmUtil.filterJvmOptions(getJvmThumbnailOptions().split("\n"));
860 }
861
862 String getCrawlerDocumentHtmlPrunedTags();
863
864 default PrunedTag[] getCrawlerDocumentHtmlPrunedTagsAsArray() {
865 PrunedTag[] tags = (PrunedTag[]) propMap.get("crawlerDocumentHtmlPrunedTags");
866 if (tags == null) {
867 tags = PrunedTag.parse(getCrawlerDocumentHtmlPrunedTags());
868 propMap.put("crawlerDocumentHtmlPrunedTags", tags);
869 }
870 return tags;
871 }
872
873 String getCrawlerDocumentCacheHtmlMimetypes();
874
875 default boolean isHtmlMimetypeForCache(final String mimetype) {
876 final String[] mimetypes = getCrawlerDocumentCacheHtmlMimetypes().split(",");
877 if (mimetypes.length == 1 && StringUtil.isBlank(mimetypes[0])) {
878 return true;
879 }
880 return stream(mimetypes).get(stream -> stream.anyMatch(s -> s.equalsIgnoreCase(mimetype)));
881 }
882
883 String getCrawlerDocumentCacheSupportedMimetypes();
884
885 default boolean isSupportedDocumentCacheMimetypes(final String mimetype) {
886 final String[] mimetypes = getCrawlerDocumentCacheSupportedMimetypes().split(",");
887 if (mimetypes.length == 1 && StringUtil.isBlank(mimetypes[0])) {
888 return true;
889 }
890 return stream(mimetypes).get(stream -> stream.anyMatch(s -> s.equalsIgnoreCase(mimetype)));
891 }
892
893 String getIndexerClickCountEnabled();
894
895 default boolean getIndexerClickCountEnabledAsBoolean() {
896 return Constants.TRUE.equalsIgnoreCase(getIndexerClickCountEnabled());
897 }
898
899 String getIndexerFavoriteCountEnabled();
900
901 default boolean getIndexerFavoriteCountEnabledAsBoolean() {
902 return Constants.TRUE.equalsIgnoreCase(getIndexerFavoriteCountEnabled());
903 }
904
905 String getApiAccessTokenRequired();
906
907 default boolean getApiAccessTokenRequiredAsBoolean() {
908 return Constants.TRUE.equalsIgnoreCase(getApiAccessTokenRequired());
909 }
910
911 String getIndexerThreadDumpEnabled();
912
913 default boolean getIndexerThreadDumpEnabledAsBoolean() {
914 return Constants.TRUE.equalsIgnoreCase(getIndexerThreadDumpEnabled());
915 }
916
917 String getIndexBackupTargets();
918
919 String getIndexBackupLogTargets();
920
921 default String[] getIndexBackupAllTargets() {
922 return split(getIndexBackupTargets() + "," + getIndexBackupLogTargets(), ",")
923 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).toArray(n -> new String[n]));
924 }
925
926 String getJobSystemJobIds();
927
928 default boolean isSystemJobId(final String id) {
929 if (StringUtil.isBlank(getJobSystemJobIds())) {
930 return false;
931 }
932 return split(getJobSystemJobIds(), ",").get(stream -> stream.anyMatch(s -> s.equals(id)));
933 }
934
935 String getSmbAvailableSidTypes();
936
937 default Integer getAvailableSmbSidType(final int sidType) {
938 @SuppressWarnings("unchecked")
939 Map<Integer, Integer> params = (Map<Integer, Integer>) propMap.get(SMB_AVAILABLE_SID_TYPES);
940 if (params == null) {
941 params = split(getSmbAvailableSidTypes(), ",").get(stream -> stream.map(s -> {
942 final String[] v = s.split(":");
943 if (v.length == 1) {
944 final int x = DfTypeUtil.toInteger(v[0].trim());
945 return new Pair<>(x, x);
946 }
947 if (v.length == 2) {
948 final int x = DfTypeUtil.toInteger(v[0].trim());
949 final int y = DfTypeUtil.toInteger(v[1].trim());
950 return new Pair<>(x, y);
951 }
952 return null;
953 }).filter(v -> v != null).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)));
954 propMap.put(SMB_AVAILABLE_SID_TYPES, params);
955 }
956 return params.get(sidType);
957 }
958
959 String getSupportedLanguages();
960
961 default String[] getSupportedLanguagesAsArray() {
962 return split(getSupportedLanguages(), ",").get(stream -> stream.filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
963 }
964
965 String getOnlineHelpSupportedLangs();
966
967 default boolean isOnlineHelpSupportedLang(final String lang) {
968 if (StringUtil.isBlank(getOnlineHelpSupportedLangs())) {
969 return false;
970 }
971 return split(getOnlineHelpSupportedLangs(), ",").get(stream -> stream.filter(StringUtil::isNotBlank).anyMatch(s -> s.equals(lang)));
972 }
973
974 String getForumSupportedLangs();
975
976 default boolean isForumSupportedLang(final String lang) {
977 if (StringUtil.isBlank(getForumSupportedLangs())) {
978 return false;
979 }
980 return split(getForumSupportedLangs(), ",").get(stream -> stream.filter(StringUtil::isNotBlank).anyMatch(s -> s.equals(lang)));
981 }
982
983 String getSupportedUploadedJsExtentions();
984
985 default String[] getSupportedUploadedJsExtentionsAsArray() {
986 return split(getSupportedUploadedJsExtentions(), ",")
987 .get(stream -> stream.filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
988 }
989
990 String getSupportedUploadedCssExtentions();
991
992 default String[] getSupportedUploadedCssExtentionsAsArray() {
993 return split(getSupportedUploadedCssExtentions(), ",")
994 .get(stream -> stream.filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
995 }
996
997 String getSupportedUploadedMediaExtentions();
998
999 default String[] getSupportedUploadedMediaExtentionsAsArray() {
1000 return split(getSupportedUploadedMediaExtentions(), ",")
1001 .get(stream -> stream.filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
1002 }
1003
1004 String getJobTemplateTitleWeb();
1005
1006 String getJobTemplateTitleFile();
1007
1008 String getJobTemplateTitleData();
1009
1010 default String getJobTemplateTitle(final String type) {
1011 if (Constants.WEB_CRAWLER_TYPE.equals(type)) {
1012 return getJobTemplateTitleWeb();
1013 }
1014 if (Constants.FILE_CRAWLER_TYPE.equals(type)) {
1015 return getJobTemplateTitleFile();
1016 }
1017 if (Constants.DATA_CRAWLER_TYPE.equals(type)) {
1018 return getJobTemplateTitleData();
1019 }
1020 return "None";
1021 }
1022
1023 String getSchedulerJobClass();
1024
1025 default Class<? extends LaJob> getSchedulerJobClassAsClass() {
1026 try {
1027 return (Class<? extends LaJob>) Class.forName(getSchedulerJobClass());
1028 } catch (final ClassNotFoundException e) {
1029 throw new ClassNotFoundRuntimeException(e);
1030 }
1031 }
1032
1033 String getSchedulerConcurrentExecMode();
1034
1035 default JobConcurrentExec getSchedulerConcurrentExecModeAsEnum() {
1036 return JobConcurrentExec.valueOf(getSchedulerConcurrentExecMode());
1037 }
1038
1039 String getCrawlerMetadataContentExcludes();
1040
1041 default boolean isCrawlerMetadataContentIncluded(final String name) {
1042 Pattern[] patterns = (Pattern[]) propMap.get(CRAWLER_METADATA_CONTENT_EXCLUDES);
1043 if (patterns == null) {
1044 patterns = split(getCrawlerMetadataContentExcludes(), ",")
1045 .get(stream -> stream.filter(StringUtil::isNotBlank).map(Pattern::compile).toArray(n -> new Pattern[n]));
1046 propMap.put(CRAWLER_METADATA_CONTENT_EXCLUDES, patterns);
1047 }
1048 return !stream(patterns).get(stream -> stream.anyMatch(p -> p.matcher(name).matches()));
1049 }
1050
1051 String getCrawlerMetadataNameMapping();
1052
1053 default Tuple3<String, String, String> getCrawlerMetadataNameMapping(final String name) {
1054 @SuppressWarnings("unchecked")
1055 Map<String, Tuple3<String, String, String>> params =
1056 (Map<String, Tuple3<String, String, String>>) propMap.get(CRAWLER_METADATA_NAME_MAPPING);
1057 if (params == null) {
1058 params = split(getCrawlerMetadataNameMapping(), "\n").get(stream -> stream.filter(StringUtil::isNotBlank).map(v -> {
1059 final String[] values = v.split("=");
1060 if (values.length == 2) {
1061 final String[] subValues = values[1].split(":", 3);
1062 if (subValues.length == 3) {
1063 return new Tuple4<>(values[0], subValues[0], subValues[1], subValues[2]);
1064 }
1065 if (subValues.length == 2) {
1066 return new Tuple4<>(values[0], subValues[0], subValues[1], StringUtil.EMPTY);
1067 }
1068 return new Tuple4<>(values[0], values[1], Constants.MAPPING_TYPE_ARRAY, StringUtil.EMPTY);
1069 }
1070 return null;
1071 }).collect(Collectors.toMap(Tuple4::getValue1, d -> new Tuple3<>(d.getValue2(), d.getValue3(), d.getValue4()))));
1072 propMap.put(CRAWLER_METADATA_NAME_MAPPING, params);
1073 }
1074 return params.get(name);
1075 }
1076
1077 default void addCrawlerMetadataNameMapping(final String name, final String fieldName, final String mappingType,
1078 final String dateFormat) {
1079 if (getCrawlerMetadataNameMapping(name) != null) {
1080 return;
1081 }
1082
1083 @SuppressWarnings("unchecked")
1084 final Map<String, Tuple3<String, String, String>> params =
1085 (Map<String, Tuple3<String, String, String>>) propMap.get(CRAWLER_METADATA_NAME_MAPPING);
1086 params.put(name, new Tuple3<>(fieldName, mappingType, dateFormat));
1087 }
1088
1089 String getSuggestPopularWordFields();
1090
1091 default String[] getSuggestPopularWordFieldsAsArray() {
1092 return split(getSuggestPopularWordFields(), "\n").get(stream -> stream.filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
1093 }
1094
1095 String getSuggestPopularWordTags();
1096
1097 default String[] getSuggestPopularWordTagsAsArray() {
1098 return split(getSuggestPopularWordTags(), "\n").get(stream -> stream.filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
1099 }
1100
1101 String getSuggestPopularWordExcludes();
1102
1103 default String[] getSuggestPopularWordExcludesAsArray() {
1104 return split(getSuggestPopularWordExcludes(), "\n")
1105 .get(stream -> stream.filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
1106 }
1107
1108 String getQueryReplaceTermWithPrefixQuery();
1109
1110 default boolean getQueryReplaceTermWithPrefixQueryAsBoolean() {
1111 return Boolean.parseBoolean(getQueryReplaceTermWithPrefixQuery());
1112 }
1113
1114 String getQueryDefaultLanguages();
1115
1116 String getQueryLanguageMapping();
1117
1118 default Map<String, String> getQueryLanguageMappingMap() {
1119 @SuppressWarnings("unchecked")
1120 Map<String, String> params = (Map<String, String>) propMap.get(QUERY_LANGUAGE_MAPPING);
1121 if (params == null) {
1122 params = stream(getQueryLanguageMapping().split("\n")).get(stream -> stream.filter(StringUtil::isNotBlank).map(v -> {
1123 final String[] values = v.split("=");
1124 if (values.length == 2) {
1125 return new Pair<>(values[0], values[1]);
1126 }
1127 return null;
1128 }).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)));
1129 propMap.put(QUERY_LANGUAGE_MAPPING, params);
1130 }
1131 return params;
1132 }
1133
1134 default String[] normalizeQueryLanguages(final String[] langs) {
1135 final Map<String, String> mapping = getQueryLanguageMappingMap();
1136 return stream(langs).get(stream -> stream.map(s -> {
1137 if (StringUtil.isBlank(s)) {
1138 return null;
1139 }
1140 final String lang1 = mapping.get(s);
1141 if (lang1 != null) {
1142 return lang1;
1143 }
1144 return mapping.get(s.split("[\\-_]")[0]);
1145 }).filter(StringUtil::isNotBlank).distinct().toArray(n -> new String[n]));
1146 }
1147
1148 default String[] getQueryLanguages(final Enumeration<Locale> locales, final String[] requestLangs) {
1149
1150 if (StringUtil.isNotBlank(getQueryDefaultLanguages())) {
1151 String[] langs = (String[]) propMap.get(QUERY_DEFAULT_LANGUAGES);
1152 if (langs == null) {
1153 langs = split(getQueryDefaultLanguages(), ",").get(stream -> stream.map(String::trim).toArray(n -> new String[n]));
1154 propMap.put(QUERY_DEFAULT_LANGUAGES, langs);
1155
1156 }
1157 return normalizeQueryLanguages(langs);
1158 }
1159
1160 if (requestLangs != null && requestLangs.length != 0) {
1161 return normalizeQueryLanguages(requestLangs);
1162 }
1163
1164 if (locales == null) {
1165 return StringUtil.EMPTY_STRINGS;
1166 }
1167
1168 return normalizeQueryLanguages(Collections.list(locales).stream().map(locale -> {
1169 final String language = locale.getLanguage();
1170 final String country = locale.getCountry();
1171 if (StringUtil.isNotBlank(language)) {
1172 if (StringUtil.isNotBlank(country)) {
1173 return language.toLowerCase(Locale.ROOT) + "-" + country.toLowerCase(Locale.ROOT);
1174 }
1175 return language.toLowerCase(Locale.ROOT);
1176 }
1177 return null;
1178 }).toArray(n -> new String[n]));
1179 }
1180
1181 default Locale getQueryLocaleFromName(final String name) {
1182 if (name == null) {
1183 return Locale.ROOT;
1184 }
1185 final String value = name.toLowerCase(Locale.ROOT);
1186 final Map<String, String> mapping = getQueryLanguageMappingMap();
1187 for (final String key : mapping.keySet()) {
1188 if (value.endsWith("_" + key.toLowerCase(Locale.ROOT))) {
1189 final String[] values = key.split("_");
1190 switch (values.length) {
1191 case 1:
1192 return new Locale(values[0]);
1193 case 2:
1194 return new Locale(values[0], values[1]);
1195 case 3:
1196 return new Locale(values[0], values[1], values[2]);
1197 default:
1198 break;
1199 }
1200 }
1201 }
1202 return Locale.ROOT;
1203 }
1204
1205 String getSupportedUploadedFiles();
1206
1207 default boolean isSupportedUploadedFile(final String name) {
1208 return split(getSuggestPopularWordExcludes(), ",")
1209 .get(stream -> stream.filter(StringUtil::isNotBlank).anyMatch(s -> s.equals(name)));
1210 }
1211
1212 String getLdapAdminUserObjectClasses();
1213
1214 default Attribute getLdapAdminUserObjectClassAttribute() {
1215 final Attribute oc = new BasicAttribute("objectClass");
1216 split(getLdapAdminUserObjectClasses(), ",").of(stream -> stream.filter(StringUtil::isNotBlank).forEach(s -> oc.add(s.trim())));
1217 return oc;
1218 }
1219
1220 String getLdapAdminUserFilter();
1221
1222 default String getLdapAdminUserFilter(final String name) {
1223 return String.format(getLdapAdminUserFilter(), LdapUtil.escapeValue(name));
1224 }
1225
1226 String getLdapAdminUserBaseDn();
1227
1228 default String getLdapAdminUserSecurityPrincipal(final String name) {
1229 final StringBuilder buf = new StringBuilder(100);
1230 buf.append(String.format(getLdapAdminUserFilter(), LdapUtil.escapeValue(name)));
1231 if (StringUtil.isNotBlank(getLdapAdminUserBaseDn())) {
1232 buf.append(',').append(getLdapAdminUserBaseDn());
1233 }
1234 return buf.toString();
1235 }
1236
1237 String getLdapAdminRoleObjectClasses();
1238
1239 default Attribute getLdapAdminRoleObjectClassAttribute() {
1240 final Attribute oc = new BasicAttribute("objectClass");
1241 split(getLdapAdminRoleObjectClasses(), ",").of(stream -> stream.filter(StringUtil::isNotBlank).forEach(s -> oc.add(s.trim())));
1242 return oc;
1243 }
1244
1245 String getLdapAdminRoleFilter();
1246
1247 default String getLdapAdminRoleFilter(final String name) {
1248 return String.format(getLdapAdminRoleFilter(), LdapUtil.escapeValue(name));
1249 }
1250
1251 String getLdapAdminRoleBaseDn();
1252
1253 default String getLdapAdminRoleSecurityPrincipal(final String name) {
1254 final StringBuilder buf = new StringBuilder(100);
1255 buf.append(String.format(getLdapAdminRoleFilter(), LdapUtil.escapeValue(name)));
1256 if (StringUtil.isNotBlank(getLdapAdminRoleBaseDn())) {
1257 buf.append(',').append(getLdapAdminRoleBaseDn());
1258 }
1259 return buf.toString();
1260 }
1261
1262 String getLdapAdminGroupObjectClasses();
1263
1264 default Attribute getLdapAdminGroupObjectClassAttribute() {
1265 final Attribute oc = new BasicAttribute("objectClass");
1266 split(getLdapAdminGroupObjectClasses(), ",").of(stream -> stream.filter(StringUtil::isNotBlank).forEach(s -> oc.add(s.trim())));
1267 return oc;
1268 }
1269
1270 String getLdapAdminGroupFilter();
1271
1272 default String getLdapAdminGroupFilter(final String name) {
1273 return String.format(getLdapAdminGroupFilter(), LdapUtil.escapeValue(name));
1274 }
1275
1276 String getLdapAdminGroupBaseDn();
1277
1278 default String getLdapAdminGroupSecurityPrincipal(final String name) {
1279 final StringBuilder buf = new StringBuilder(100);
1280 buf.append(String.format(getLdapAdminGroupFilter(), LdapUtil.escapeValue(name)));
1281 if (StringUtil.isNotBlank(getLdapAdminGroupBaseDn())) {
1282 buf.append(',').append(getLdapAdminGroupBaseDn());
1283 }
1284 return buf.toString();
1285 }
1286
1287 String getAuthenticationAdminUsers();
1288
1289 default boolean isAdminUser(final String username) {
1290 return split(getAuthenticationAdminUsers(), ",").get(stream -> stream.anyMatch(s -> s.equals(username)));
1291 }
1292
1293 boolean isLdapAdminEnabled();
1294
1295 default boolean isLdapAdminEnabled(final String username) {
1296 if (isAdminUser(username)) {
1297 return false;
1298 }
1299 return isLdapAdminEnabled();
1300 }
1301
1302 String getRoleSearchDefaultPermissions();
1303
1304 default String[] getSearchDefaultPermissionsAsArray() {
1305 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
1306 return split(getRoleSearchDefaultPermissions(), ",").get(stream -> stream.map(p -> permissionHelper.encode(p))
1307 .filter(StringUtil::isNotBlank)
1308 .distinct()
1309 .toArray(n -> new String[n]));
1310 }
1311
1312 String getRoleSearchDefaultDisplayPermissions();
1313
1314 default String[] getSearchDefaultDisplayEncodedPermissions() {
1315 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
1316 return split(getRoleSearchDefaultDisplayPermissions(), ",").get(stream -> stream.map(p -> permissionHelper.encode(p))
1317 .filter(StringUtil::isNotBlank)
1318 .distinct()
1319 .toArray(n -> new String[n]));
1320 }
1321
1322 default String getSearchDefaultDisplayPermission() {
1323 return split(getRoleSearchDefaultDisplayPermissions(), ",")
1324 .get(stream -> stream.filter(StringUtil::isNotBlank).distinct().collect(Collectors.joining("\n")));
1325 }
1326
1327 String getQueryGeoFields();
1328
1329 default String[] getQueryGeoFieldsAsArray() {
1330 return split(getQueryGeoFields(), ",")
1331 .get(stream -> stream.map(String::trim).filter(StringUtil::isNotBlank).toArray(n -> new String[n]));
1332 }
1333
1334 String getSuggestSearchLogPermissions();
1335
1336 default boolean isValidSearchLogPermissions(final String[] permissions) {
1337 if (permissions == null) {
1338 return false;
1339 }
1340 @SuppressWarnings("unchecked")
1341 List<String> validPermissionList = (List<String>) propMap.get(SUGGEST_SEARCH_LOG_PERMISSIONS);
1342 if (validPermissionList == null) {
1343 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
1344 validPermissionList = split(getSuggestSearchLogPermissions(), ",")
1345 .get(stream -> stream.map(s -> permissionHelper.encode(s)).filter(StringUtil::isNotBlank).collect(Collectors.toList()));
1346 propMap.put(SUGGEST_SEARCH_LOG_PERMISSIONS, validPermissionList);
1347 }
1348 final List<String> list = validPermissionList;
1349 return stream(permissions).get(stream -> stream.allMatch(v -> list.contains(v)));
1350 }
1351
1352 String getRoleSearchUserPrefix();
1353
1354 String getRoleSearchGuestPermissions();
1355
1356 default List<String> getSearchGuestRoleList() {
1357 @SuppressWarnings("unchecked")
1358 List<String> list = (List<String>) propMap.get(SEARCH_GUEST_ROLE_LIST);
1359 if (list == null) {
1360 final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
1361 list = split(getRoleSearchGuestPermissions(), ",")
1362 .get(stream -> stream.map(s -> permissionHelper.encode(s)).filter(StringUtil::isNotBlank).collect(Collectors.toList()));
1363 list.add(getRoleSearchUserPrefix() + Constants.GUEST_USER);
1364 propMap.put(SEARCH_GUEST_ROLE_LIST, list);
1365 }
1366 return list;
1367 }
1368
1369 String getIndexAdminArrayFields();
1370
1371 default Set<String> getIndexAdminArrayFieldSet() {
1372 @SuppressWarnings("unchecked")
1373 Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_ARRAY_FIELD_SET);
1374 if (fieldSet == null) {
1375 fieldSet = split(getIndexAdminArrayFields(), ",")
1376 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
1377 propMap.put(INDEX_ADMIN_ARRAY_FIELD_SET, fieldSet);
1378 }
1379 return fieldSet;
1380 }
1381
1382 default boolean validateIndexArrayFields(final Map<String, Object> source) {
1383 return invalidIndexArrayFields(source).isEmpty();
1384 }
1385
1386 default List<String> invalidIndexArrayFields(final Map<String, Object> source) {
1387
1388 return split(getIndexAdminArrayFields(), ",").get(stream -> stream.filter(StringUtil::isNotBlank)
1389 .map(String::trim)
1390 .filter(s -> isNonEmptyValue(source.get(s)))
1391 .filter(s -> false)
1392 .collect(Collectors.toList()));
1393 }
1394
1395 String getIndexAdminDateFields();
1396
1397 default Set<String> getIndexAdminDateFieldSet() {
1398 @SuppressWarnings("unchecked")
1399 Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_DATE_FIELD_SET);
1400 if (fieldSet == null) {
1401 fieldSet = split(getIndexAdminDateFields(), ",")
1402 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
1403 propMap.put(INDEX_ADMIN_DATE_FIELD_SET, fieldSet);
1404 }
1405 return fieldSet;
1406 }
1407
1408 default boolean validateIndexDateFields(final Map<String, Object> source) {
1409 return invalidIndexDateFields(source).isEmpty();
1410 }
1411
1412 default List<String> invalidIndexDateFields(final Map<String, Object> source) {
1413 return split(getIndexAdminDateFields(), ",").get(
1414 stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))).filter(s -> {
1415 final Object obj = source.get(s);
1416 if (obj instanceof Date) {
1417 return false;
1418 }
1419 return !validateDateTimeString(source.get(s));
1420 }).collect(Collectors.toList()));
1421 }
1422
1423 default boolean validateDateTimeString(final Object obj) {
1424 if (FessFunctions.parseDate(obj.toString()) != null) {
1425 return true;
1426 }
1427 return false;
1428 }
1429
1430 String getIndexAdminIntegerFields();
1431
1432 default Set<String> getIndexAdminIntegerFieldSet() {
1433 @SuppressWarnings("unchecked")
1434 Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_INTEGER_FIELD_SET);
1435 if (fieldSet == null) {
1436 fieldSet = split(getIndexAdminIntegerFields(), ",")
1437 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
1438 propMap.put(INDEX_ADMIN_INTEGER_FIELD_SET, fieldSet);
1439 }
1440 return fieldSet;
1441 }
1442
1443 default boolean validateIndexIntegerFields(final Map<String, Object> source) {
1444 return invalidIndexIntegerFields(source).isEmpty();
1445 }
1446
1447 default List<String> invalidIndexIntegerFields(final Map<String, Object> source) {
1448 final IntegerTypeValidator integerValidator = new IntegerTypeValidator();
1449 return split(getIndexAdminIntegerFields(), ",").get(
1450 stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))).filter(s -> {
1451 final Object obj = source.get(s);
1452 if (obj instanceof Number) {
1453 return false;
1454 }
1455 return !integerValidator.isValid(obj.toString(), null);
1456 }).collect(Collectors.toList()));
1457 }
1458
1459 String getIndexAdminLongFields();
1460
1461 default Set<String> getIndexAdminLongFieldSet() {
1462 @SuppressWarnings("unchecked")
1463 Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_LONG_FIELD_SET);
1464 if (fieldSet == null) {
1465 fieldSet = split(getIndexAdminLongFields(), ",")
1466 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
1467 propMap.put(INDEX_ADMIN_LONG_FIELD_SET, fieldSet);
1468 }
1469 return fieldSet;
1470 }
1471
1472 default boolean validateIndexLongFields(final Map<String, Object> source) {
1473 return invalidIndexLongFields(source).isEmpty();
1474 }
1475
1476 default List<String> invalidIndexLongFields(final Map<String, Object> source) {
1477 final LongTypeValidator longValidator = new LongTypeValidator();
1478 return split(getIndexAdminLongFields(), ",").get(
1479 stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> isNonEmptyValue(source.get(s))).filter(s -> {
1480 final Object obj = source.get(s);
1481 if (obj instanceof Number) {
1482 return false;
1483 }
1484 return !longValidator.isValid(obj.toString(), null);
1485 }).collect(Collectors.toList()));
1486 }
1487
1488 String getIndexAdminFloatFields();
1489
1490 default Set<String> getIndexAdminFloatFieldSet() {
1491 @SuppressWarnings("unchecked")
1492 Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_FLOAT_FIELD_SET);
1493 if (fieldSet == null) {
1494 fieldSet = split(getIndexAdminFloatFields(), ",")
1495 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
1496 propMap.put(INDEX_ADMIN_FLOAT_FIELD_SET, fieldSet);
1497 }
1498 return fieldSet;
1499 }
1500
1501 default boolean validateIndexFloatFields(final Map<String, Object> source) {
1502 return invalidIndexFloatFields(source).isEmpty();
1503 }
1504
1505 default List<String> invalidIndexFloatFields(final Map<String, Object> source) {
1506 final FloatTypeValidator floatValidator = new FloatTypeValidator();
1507 return split(getIndexAdminFloatFields(), ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> {
1508 final Object obj = source.get(s);
1509 if (obj instanceof Number) {
1510 return false;
1511 }
1512 return !floatValidator.isValid(obj.toString(), null);
1513 }).collect(Collectors.toList()));
1514 }
1515
1516 String getIndexAdminDoubleFields();
1517
1518 default Set<String> getIndexAdminDoubleFieldSet() {
1519 @SuppressWarnings("unchecked")
1520 Set<String> fieldSet = (Set<String>) propMap.get(INDEX_ADMIN_DOUBLE_FIELD_SET);
1521 if (fieldSet == null) {
1522 fieldSet = split(getIndexAdminDoubleFields(), ",")
1523 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
1524 propMap.put(INDEX_ADMIN_DOUBLE_FIELD_SET, fieldSet);
1525 }
1526 return fieldSet;
1527 }
1528
1529 default boolean validateIndexDoubleFields(final Map<String, Object> source) {
1530 return invalidIndexDoubleFields(source).isEmpty();
1531 }
1532
1533 default List<String> invalidIndexDoubleFields(final Map<String, Object> source) {
1534 final DoubleTypeValidator doubleValidator = new DoubleTypeValidator();
1535 return split(getIndexAdminDoubleFields(), ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).filter(s -> {
1536 final Object obj = source.get(s);
1537 if (obj instanceof Number) {
1538 return false;
1539 }
1540 return !doubleValidator.isValid(obj.toString(), null);
1541 }).collect(Collectors.toList()));
1542 }
1543
1544 default Map<String, Object> convertToEditableDoc(final Map<String, Object> source) {
1545
1546 final Set<String> arrayFieldSet = getIndexAdminArrayFieldSet();
1547 final Set<String> dateFieldSet = getIndexAdminDateFieldSet();
1548 final Set<String> integerFieldSet = getIndexAdminIntegerFieldSet();
1549 final Set<String> longFieldSet = getIndexAdminLongFieldSet();
1550 final Set<String> floatFieldSet = getIndexAdminFloatFieldSet();
1551 final Set<String> doubleFieldSet = getIndexAdminDoubleFieldSet();
1552
1553 return source.entrySet().stream().map(e -> {
1554 final String key = e.getKey();
1555 Object value = e.getValue();
1556 if (value == null) {
1557 value = StringUtil.EMPTY;
1558 }
1559 if (value instanceof String || value == null) {
1560 return new Pair<>(key, value);
1561 }
1562 if (arrayFieldSet.contains(key)) {
1563 if (value instanceof String[]) {
1564 value = stream((String[]) value).get(stream -> stream.collect(Collectors.joining("\n")));
1565 } else if (value instanceof List) {
1566 @SuppressWarnings("unchecked")
1567 final List<String> list = (List<String>) value;
1568 value = list.stream().collect(Collectors.joining("\n"));
1569 }
1570 } else if (dateFieldSet.contains(key)) {
1571 value = FessFunctions.formatDate((Date) value);
1572 } else if (integerFieldSet.contains(key) || longFieldSet.contains(key) || floatFieldSet.contains(key)
1573 || doubleFieldSet.contains(key)) {
1574 value = value.toString();
1575 }
1576 return new Pair<>(key, value);
1577 }).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond));
1578 }
1579
1580 default Map<String, Object> convertToStorableDoc(final Map<String, Object> source) {
1581
1582 final Set<String> arrayFieldSet = getIndexAdminArrayFieldSet();
1583 final Set<String> dateFieldSet = getIndexAdminDateFieldSet();
1584 final Set<String> integerFieldSet = getIndexAdminIntegerFieldSet();
1585 final Set<String> longFieldSet = getIndexAdminLongFieldSet();
1586 final Set<String> floatFieldSet = getIndexAdminFloatFieldSet();
1587 final Set<String> doubleFieldSet = getIndexAdminDoubleFieldSet();
1588
1589 return source.entrySet().stream().filter(e -> isNonEmptyValue(e.getValue())).map(e -> {
1590 final String key = e.getKey();
1591 Object value = e.getValue();
1592 if (arrayFieldSet.contains(key)) {
1593 if (value instanceof String[]) {
1594 value = Arrays.stream((String[]) value).toList();
1595 } else if (value instanceof List<?>) {
1596
1597 } else {
1598 value = split(value.toString(), "\n")
1599 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toList()));
1600 }
1601 } else if (dateFieldSet.contains(key)) {
1602
1603 if (value instanceof Date) {
1604
1605 } else {
1606 value = FessFunctions.parseDate(value.toString());
1607 }
1608 } else if (integerFieldSet.contains(key)) {
1609 if (value instanceof final Number num) {
1610 value = num.intValue();
1611 } else {
1612 value = DfTypeUtil.toInteger(value.toString());
1613 }
1614 } else if (longFieldSet.contains(key)) {
1615 if (value instanceof final Number num) {
1616 value = num.longValue();
1617 } else {
1618 value = DfTypeUtil.toLong(value.toString());
1619 }
1620 } else if (floatFieldSet.contains(key)) {
1621 if (value instanceof final Number num) {
1622 value = num.floatValue();
1623 } else {
1624 value = DfTypeUtil.toFloat(value.toString());
1625 }
1626 } else if (doubleFieldSet.contains(key)) {
1627 if (value instanceof final Number num) {
1628 value = num.doubleValue();
1629 } else {
1630 value = DfTypeUtil.toDouble(value.toString());
1631 }
1632 }
1633 return new Pair<>(key, value);
1634 }).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond));
1635 }
1636
1637 String getIndexAdminRequiredFields();
1638
1639 default boolean validateIndexRequiredFields(final Map<String, Object> source) {
1640 return invalidIndexRequiredFields(source).isEmpty();
1641 }
1642
1643 default List<String> invalidIndexRequiredFields(final Map<String, Object> source) {
1644 final RequiredValidator requiredValidator = new RequiredValidator();
1645 return split(getIndexAdminRequiredFields(), ",").get(stream -> stream.filter(StringUtil::isNotBlank)
1646 .map(String::trim)
1647 .filter(s -> !requiredValidator.isValid(source.get(s), null))
1648 .collect(Collectors.toList()));
1649 }
1650
1651 default boolean isNonEmptyValue(final Object value) {
1652 final RequiredValidator requiredValidator = new RequiredValidator();
1653 return requiredValidator.isValid(value, null);
1654 }
1655
1656 String getCrawlerDocumentSpaceChars();
1657
1658 default int[] getCrawlerDocumentSpaceCharsAsArray() {
1659 return getCrawlerDocumentCharsAsArray(CRAWLER_DOCUMENT_SPACE_CHARS, getCrawlerDocumentSpaceChars());
1660 }
1661
1662 default String[] getCrawlerDocumentSpaces() {
1663 String[] spaces = (String[]) propMap.get(CRAWLER_DOCUMENT_SPACES);
1664 if (spaces == null) {
1665 spaces = Arrays.stream(getCrawlerDocumentSpaceCharsAsArray()).mapToObj(Character::toString).toArray(n -> new String[n]);
1666 propMap.put(CRAWLER_DOCUMENT_SPACES, spaces);
1667 }
1668 return spaces;
1669 }
1670
1671 default int[] getCrawlerDocumentCharsAsArray(final String key, final String spaceStr) {
1672 int[] spaceChars = (int[]) propMap.get(key);
1673 if (spaceChars == null) {
1674 if (spaceStr.startsWith("u")) {
1675 spaceChars = split(spaceStr, "u")
1676 .get(stream -> stream.filter(StringUtil::isNotBlank).mapToInt(s -> Integer.parseInt(s, 16)).toArray());
1677 } else {
1678
1679 final int length = spaceStr.length();
1680 spaceChars = new int[length];
1681 for (int i = 0; i < length; i++) {
1682 spaceChars[i] = spaceStr.codePointAt(i);
1683 }
1684 }
1685 propMap.put(key, spaceChars);
1686 }
1687 return spaceChars;
1688 }
1689
1690 String getCrawlerDocumentFullstopChars();
1691
1692 default boolean endsWithFullstop(final String s) {
1693 if (StringUtil.isBlank(s)) {
1694 return false;
1695 }
1696 for (final int i : getCrawlerDocumentFullstopCharsAsArray()) {
1697 if (s.endsWith(String.valueOf(i))) {
1698 return true;
1699 }
1700 }
1701 return false;
1702 }
1703
1704 default int[] getCrawlerDocumentFullstopCharsAsArray() {
1705 return getCrawlerDocumentCharsAsArray(CRAWLER_DOCUMENT_FULLSTOP_CHARS, getCrawlerDocumentFullstopChars());
1706 }
1707
1708 String getQueryAdditionalResponseFields();
1709
1710 default String[] getQueryAdditionalResponseFields(final String... fields) {
1711 final List<String> list = new ArrayList<>(fields.length + 10);
1712 stream(fields).of(stream -> stream.forEach(list::add));
1713 split(getQueryAdditionalResponseFields(), ",")
1714 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1715 return list.toArray(new String[list.size()]);
1716 }
1717
1718 String getQueryAdditionalScrollResponseFields();
1719
1720 default String[] getQueryAdditionalScrollResponseFields(final String... fields) {
1721 final List<String> list = new ArrayList<>(fields.length + 10);
1722 stream(fields).of(stream -> stream.forEach(list::add));
1723 split(getQueryAdditionalScrollResponseFields(), ",")
1724 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1725 return list.toArray(new String[list.size()]);
1726 }
1727
1728 String getQueryAdditionalCacheResponseFields();
1729
1730 default String[] getQueryAdditionalCacheResponseFields(final String... fields) {
1731 final List<String> list = new ArrayList<>(fields.length + 10);
1732 stream(fields).of(stream -> stream.forEach(list::add));
1733 split(getQueryAdditionalCacheResponseFields(), ",")
1734 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1735 return list.toArray(new String[list.size()]);
1736 }
1737
1738 String getQueryAdditionalHighlightedFields();
1739
1740 default String[] getQueryAdditionalHighlightedFields(final String... fields) {
1741 final List<String> list = new ArrayList<>(fields.length + 10);
1742 stream(fields).of(stream -> stream.forEach(list::add));
1743 split(getQueryAdditionalHighlightedFields(), ",")
1744 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1745 return list.toArray(new String[list.size()]);
1746 }
1747
1748 String getQueryAdditionalSearchFields();
1749
1750 default String[] getQueryAdditionalSearchFields(final String... fields) {
1751 final List<String> list = new ArrayList<>(fields.length + 10);
1752 stream(fields).of(stream -> stream.forEach(list::add));
1753 split(getQueryAdditionalSearchFields(), ",")
1754 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1755 return list.toArray(new String[list.size()]);
1756 }
1757
1758 String getQueryAdditionalFacetFields();
1759
1760 default String[] getQueryAdditionalFacetFields(final String... fields) {
1761 final List<String> list = new ArrayList<>(fields.length + 10);
1762 stream(fields).of(stream -> stream.forEach(list::add));
1763 split(getQueryAdditionalFacetFields(), ",")
1764 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1765 return list.toArray(new String[list.size()]);
1766 }
1767
1768 String getQueryAdditionalSortFields();
1769
1770 default String[] getQueryAdditionalSortFields(final String... fields) {
1771 final List<String> list = new ArrayList<>(fields.length + 10);
1772 stream(fields).of(stream -> stream.forEach(list::add));
1773 split(getQueryAdditionalSortFields(), ",").of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1774 return list.toArray(new String[list.size()]);
1775 }
1776
1777 String getQueryAdditionalApiResponseFields();
1778
1779 default String[] getQueryAdditionalApiResponseFields(final String... fields) {
1780 final List<String> list = new ArrayList<>(fields.length + 10);
1781 stream(fields).of(stream -> stream.forEach(list::add));
1782 split(getQueryAdditionalApiResponseFields(), ",")
1783 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1784 return list.toArray(new String[list.size()]);
1785 }
1786
1787 String getQueryAdditionalNotAnalyzedFields();
1788
1789 default String[] getQueryAdditionalNotAnalyzedFields(final String... fields) {
1790 final List<String> list = new ArrayList<>(fields.length + 10);
1791 stream(fields).of(stream -> stream.forEach(list::add));
1792 split(getQueryAdditionalNotAnalyzedFields(), ",")
1793 .of(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).forEach(list::add));
1794 return list.toArray(new String[list.size()]);
1795 }
1796
1797 String getThumbnailGeneratorTargets();
1798
1799 default String[] getThumbnailGeneratorTargetsAsArray() {
1800 return getThumbnailGeneratorTargets().split(",");
1801
1802 }
1803
1804 String getApiAdminAccessPermissions();
1805
1806 default Set<String> getApiAdminAccessPermissionSet() {
1807 @SuppressWarnings("unchecked")
1808 Set<String> fieldSet = (Set<String>) propMap.get(API_ADMIN_ACCESS_PERMISSION_SET);
1809 if (fieldSet == null) {
1810 fieldSet = split(getApiAdminAccessPermissions(), ",")
1811 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
1812 propMap.put(API_ADMIN_ACCESS_PERMISSION_SET, fieldSet);
1813 }
1814 return fieldSet;
1815 }
1816
1817 default boolean isApiAdminAccessAllowed(final Set<String> accessPermissions) {
1818 return getApiAdminAccessPermissionSet().stream().anyMatch(s -> accessPermissions.contains(s));
1819 }
1820
1821 String getUserCodePattern();
1822
1823 Integer getUserCodeMinLengthAsInteger();
1824
1825 Integer getUserCodeMaxLengthAsInteger();
1826
1827 default boolean isValidUserCode(final String userCode) {
1828 if (userCode == null) {
1829 return false;
1830 }
1831
1832 final int length = userCode.length();
1833 if (getUserCodeMinLengthAsInteger().intValue() > length || getUserCodeMaxLengthAsInteger().intValue() < length) {
1834 return false;
1835 }
1836
1837 Pattern pattern = (Pattern) propMap.get(USER_CODE_PATTERN);
1838 if (pattern == null) {
1839 pattern = Pattern.compile(getUserCodePattern());
1840 propMap.put(USER_CODE_PATTERN, pattern);
1841 }
1842 return pattern.matcher(userCode).matches();
1843 }
1844
1845 String getQueryCollapseInnerHitsSorts();
1846
1847 @SuppressWarnings("rawtypes")
1848 default OptionalThing<SortBuilder[]> getQueryCollapseInnerHitsSortBuilders() {
1849 @SuppressWarnings("unchecked")
1850 OptionalThing<SortBuilder[]> ot = (OptionalThing<SortBuilder[]>) propMap.get(QUERY_COLLAPSE_INNER_HITS_SORTS);
1851 if (ot == null) {
1852 final String sorts = getQueryCollapseInnerHitsSorts();
1853 if (StringUtil.isBlank(sorts)) {
1854 ot = OptionalThing.empty();
1855 } else {
1856 final SortBuilder[] sortBuilders = split(sorts, ",").get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> {
1857 final String[] values = s.split(":");
1858 if (values.length > 1) {
1859 return SortBuilders.fieldSort(values[0]).order("desc".equalsIgnoreCase(values[0]) ? SortOrder.DESC : SortOrder.ASC);
1860 }
1861 return SortBuilders.fieldSort(values[0]).order(SortOrder.ASC);
1862 }).toArray(n -> new SortBuilder[n]));
1863 ot = OptionalThing.of(sortBuilders);
1864 }
1865 propMap.put(QUERY_COLLAPSE_INNER_HITS_SORTS, ot);
1866 }
1867 return ot;
1868 }
1869
1870 String getVirtualHostHeaders();
1871
1872 default String getVirtualHostHeaderValue() {
1873 final String value = getVirtualHostValue();
1874 if (StringUtil.isNotBlank(value)) {
1875 return value;
1876 }
1877 return getVirtualHostHeaders();
1878 }
1879
1880 @SuppressWarnings("unchecked")
1881 default Tuple3<String, String, String>[] getVirtualHosts() {
1882 Tuple3<String, String, String>[] hosts = (Tuple3<String, String, String>[]) propMap.get(VIRTUAL_HOST_HEADERS);
1883 if (hosts == null) {
1884 hosts = split(getVirtualHostHeaderValue(), "\n").get(stream -> stream.map(s -> {
1885 final String[] v1 = s.split("=");
1886 if (v1.length == 2) {
1887 final String[] v2 = v1[0].split(":", 2);
1888 if (v2.length == 2) {
1889 return new Tuple3<>(v2[0].trim(), v2[1].trim(), v1[1].replaceAll("[^a-zA-Z0-9_]", StringUtil.EMPTY).trim());
1890 }
1891 }
1892 return null;
1893 }).filter(v -> {
1894 if (v == null) {
1895 return false;
1896 }
1897 if ("admin".equalsIgnoreCase(v.getValue3()) || "common".equalsIgnoreCase(v.getValue3())
1898 || "error".equalsIgnoreCase(v.getValue3()) || "login".equalsIgnoreCase(v.getValue3())
1899 || "profile".equalsIgnoreCase(v.getValue3())) {
1900 return false;
1901 }
1902 return true;
1903 }).toArray(n -> new Tuple3[n]));
1904 propMap.put(VIRTUAL_HOST_HEADERS, hosts);
1905 }
1906 return hosts;
1907 }
1908
1909 String getCrawlerFailureUrlStatusCodes();
1910
1911 default boolean isCrawlerFailureUrlStatusCodes(final int code) {
1912 int[] codes = (int[]) propMap.get(CRAWLER_FAILURE_URL_STATUS_CODES);
1913 if (codes == null) {
1914 codes = split(getCrawlerFailureUrlStatusCodes(), ",")
1915 .get(stream -> stream.filter(StringUtil::isNotBlank).mapToInt(Integer::parseInt).toArray());
1916 propMap.put(CRAWLER_FAILURE_URL_STATUS_CODES, codes);
1917 }
1918 for (final int v : codes) {
1919 if (v == code) {
1920 return true;
1921 }
1922 }
1923 return false;
1924 }
1925
1926 Integer getThumbnailHtmlImageMinWidthAsInteger();
1927
1928 Integer getThumbnailHtmlImageMinHeightAsInteger();
1929
1930 java.math.BigDecimal getThumbnailHtmlImageMaxAspectRatioAsDecimal();
1931
1932 default boolean validateThumbnailSize(final int width, final int height) {
1933 if (width <= 0 || height <= 0 || width < getThumbnailHtmlImageMinWidthAsInteger().intValue()
1934 || height < getThumbnailHtmlImageMinHeightAsInteger().intValue()) {
1935 return false;
1936 }
1937
1938 final float ratio = getThumbnailHtmlImageMaxAspectRatioAsDecimal().floatValue();
1939 if ((float) width / (float) height > ratio || (float) height / (float) width > ratio) {
1940 return false;
1941 }
1942
1943 return true;
1944 }
1945
1946 String getHttpProxyHost();
1947
1948 Integer getHttpProxyPortAsInteger();
1949
1950 String getHttpProxyUsername();
1951
1952 String getHttpProxyPassword();
1953
1954 default Proxy getHttpProxy() {
1955 Proxy proxy = (Proxy) propMap.get(HTML_PROXY);
1956 if (proxy == null) {
1957 if (StringUtil.isNotBlank(getHttpProxyHost()) && getHttpProxyPortAsInteger() != null) {
1958 final SocketAddress addr = new InetSocketAddress(getHttpProxyHost(), getHttpProxyPortAsInteger());
1959 proxy = new Proxy(Type.HTTP, addr);
1960 if (StringUtil.isNotBlank(getHttpProxyUsername())) {
1961 Authenticator.setDefault(new Authenticator() {
1962 @Override
1963 protected PasswordAuthentication getPasswordAuthentication() {
1964 return new PasswordAuthentication(getHttpProxyUsername(), getHttpProxyPassword().toCharArray());
1965 }
1966 });
1967 }
1968 } else {
1969 proxy = Proxy.NO_PROXY;
1970 }
1971 propMap.put(HTML_PROXY, proxy);
1972 }
1973 return proxy;
1974 }
1975
1976 String getThumbnailHtmlImageExcludeExtensions();
1977
1978 default boolean isThumbnailHtmlImageUrl(final String url) {
1979 if (StringUtil.isBlank(url)) {
1980 return false;
1981 }
1982
1983 String[] excludeExtensions = (String[]) propMap.get(THUMBNAIL_HTML_IMAGE_EXCLUDE_EXTENSIONS);
1984 if (excludeExtensions == null) {
1985 excludeExtensions =
1986 split(getThumbnailHtmlImageExcludeExtensions(), ",").get(stream -> stream.map(s -> s.toLowerCase(Locale.ROOT).trim())
1987 .filter(StringUtil::isNotBlank)
1988 .toArray(n -> new String[n]));
1989 propMap.put(THUMBNAIL_HTML_IMAGE_EXCLUDE_EXTENSIONS, excludeExtensions);
1990 }
1991
1992 final String u = url.toLowerCase(Locale.ROOT);
1993 return !stream(excludeExtensions).get(stream -> stream.anyMatch(s -> u.endsWith(s)));
1994 }
1995
1996 String getQueryGsaResponseFields();
1997
1998 default boolean isGsaResponseFields(final String name) {
1999 @SuppressWarnings("unchecked")
2000 Set<String> gsaResponseFieldSet = (Set<String>) propMap.get(QUERY_GSA_RESPONSE_FIELDS);
2001 if (gsaResponseFieldSet == null) {
2002 gsaResponseFieldSet = split(getQueryGsaResponseFields(), ",").get(stream -> stream.map(s -> s.toLowerCase(Locale.ROOT).trim())
2003 .filter(StringUtil::isNotBlank)
2004 .collect(Collectors.toSet()));
2005 propMap.put(QUERY_GSA_RESPONSE_FIELDS, gsaResponseFieldSet);
2006 }
2007 return gsaResponseFieldSet.contains(name.toLowerCase(Locale.ROOT));
2008 }
2009
2010 String getApiSearchAcceptReferers();
2011
2012 default boolean isAcceptedSearchReferer(final String referer) {
2013 Pattern[] patterns = (Pattern[]) propMap.get(API_SEARCH_ACCEPT_REFERERS);
2014 if (patterns == null) {
2015 final String refs = getApiSearchAcceptReferers();
2016 if (StringUtil.isBlank(refs)) {
2017 patterns = new Pattern[0];
2018 } else {
2019 patterns = split(refs, "\n").get(
2020 stream -> stream.filter(StringUtil::isNotBlank).map(s -> Pattern.compile(s.trim())).toArray(n -> new Pattern[n]));
2021 }
2022 propMap.put(API_SEARCH_ACCEPT_REFERERS, patterns);
2023 }
2024 if (patterns.length == 0) {
2025 return true;
2026 }
2027
2028 if (referer == null) {
2029 return false;
2030 }
2031 return Arrays.stream(patterns).anyMatch(p -> p.matcher(referer).matches());
2032 }
2033
2034 String getQueryHighlightContentDescriptionFields();
2035
2036 default String[] getQueryHighlightContentDescriptionFieldsAsArray() {
2037 return split(getQueryHighlightContentDescriptionFields(), ",")
2038 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).toArray(n -> new String[n]));
2039 }
2040
2041 boolean isLdapIgnoreNetbiosName();
2042
2043 default String getCanonicalLdapName(final String name) {
2044 if (isLdapIgnoreNetbiosName()) {
2045 final String[] values = name.split("\\\\");
2046 if (values.length == 0) {
2047 return null;
2048 }
2049 if (values.length == 1) {
2050 return values[0];
2051 }
2052 return String.join("\\", Arrays.copyOfRange(values, 1, values.length));
2053 }
2054 return name;
2055 }
2056
2057 String getLoggingSearchDocsFields();
2058
2059 default String[] getLoggingSearchDocsFieldsAsArray() {
2060 String[] fields = (String[]) propMap.get(LOGGING_SEARCH_DOCS_FIELDS);
2061 if (fields == null) {
2062 fields = split(getLoggingSearchDocsFields(), ",").get(stream -> stream.map(String::trim).toArray(n -> new String[n]));
2063 propMap.put(LOGGING_SEARCH_DOCS_FIELDS, fields);
2064 }
2065 return fields;
2066 }
2067
2068 String getSchedulerTargetName();
2069
2070 default boolean isSchedulerTarget(final String target) {
2071 if (StringUtil.isBlank(target)) {
2072 return true;
2073 }
2074
2075 final String myName = getSchedulerTargetName();
2076
2077 final String[] targets = target.split(",");
2078 for (String name : targets) {
2079 name = name.trim();
2080 if (Constants.DEFAULT_JOB_TARGET.equalsIgnoreCase(name) || StringUtil.isNotBlank(myName) && myName.equalsIgnoreCase(name)) {
2081 return true;
2082 }
2083 }
2084 return false;
2085 }
2086
2087 String getApiGsaResponseHeaders();
2088
2089 default List<Pair<String, String>> getApiGsaResponseHeaderList() {
2090 @SuppressWarnings("unchecked")
2091 List<Pair<String, String>> list = (List<Pair<String, String>>) propMap.get(API_GSA_RESPONSE_HEADER_LIST);
2092 if (list == null) {
2093 list = split(getApiGsaResponseHeaders(), "\n").get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> {
2094 final String[] values = s.split(":", 2);
2095 if (values.length == 2) {
2096 return new Pair<>(values[0], values[1]);
2097 }
2098 return new Pair<>(values[0], StringUtil.EMPTY);
2099 }).collect(Collectors.toList()));
2100 propMap.put(API_GSA_RESPONSE_HEADER_LIST, list);
2101 }
2102 return list;
2103 }
2104
2105 String getApiJsonResponseHeaders();
2106
2107 default List<Pair<String, String>> getApiJsonResponseHeaderList() {
2108 @SuppressWarnings("unchecked")
2109 List<Pair<String, String>> list = (List<Pair<String, String>>) propMap.get(API_JSON_RESPONSE_HEADER_LIST);
2110 if (list == null) {
2111 list = split(getApiJsonResponseHeaders(), "\n").get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> {
2112 final String[] values = s.split(":", 2);
2113 if (values.length == 2) {
2114 return new Pair<>(values[0], values[1]);
2115 }
2116 return new Pair<>(values[0], StringUtil.EMPTY);
2117 }).collect(Collectors.toList()));
2118 propMap.put(API_JSON_RESPONSE_HEADER_LIST, list);
2119 }
2120 return list;
2121 }
2122
2123 String getApiDashboardResponseHeaders();
2124
2125 default List<Pair<String, String>> getApiDashboardResponseHeaderList() {
2126 @SuppressWarnings("unchecked")
2127 List<Pair<String, String>> list = (List<Pair<String, String>>) propMap.get(API_DASHBOARD_RESPONSE_HEADER_LIST);
2128 if (list == null) {
2129 list = split(getApiDashboardResponseHeaders(), "\n").get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> {
2130 final String[] values = s.split(":", 2);
2131 if (values.length == 2) {
2132 return new Pair<>(values[0], values[1]);
2133 }
2134 return new Pair<>(values[0], StringUtil.EMPTY);
2135 }).collect(Collectors.toList()));
2136 propMap.put(API_DASHBOARD_RESPONSE_HEADER_LIST, list);
2137 }
2138 return list;
2139 }
2140
2141 String getApiCorsAllowOrigin();
2142
2143 default List<String> getApiCorsAllowOriginList() {
2144 @SuppressWarnings("unchecked")
2145 List<String> list = (List<String>) propMap.get(CORS_ALLOW_ORIGIN);
2146 if (list == null) {
2147 list = split(getApiCorsAllowOrigin(), "\n")
2148 .get(stream -> stream.map(String::trim).filter(StringUtil::isNotEmpty).collect(Collectors.toList()));
2149 propMap.put(CORS_ALLOW_ORIGIN, list);
2150 }
2151 return list;
2152 }
2153
2154 String getIndexerLanguageFields();
2155
2156 default String[] getIndexerLanguageFieldsAsArray() {
2157 return split(getIndexerLanguageFields(), ",").get(stream -> stream.map(String::trim).toArray(n -> new String[n]));
2158
2159 }
2160
2161 String getSessionTrackingModes();
2162
2163 default Set<String> getSessionTrackingModesAsSet() {
2164 return split(getSessionTrackingModes(), ",")
2165 .get(stream -> stream.map(s -> s.trim().toUpperCase(Locale.ENGLISH)).collect(Collectors.toSet()));
2166 }
2167
2168 String getQueryTrackTotalHits();
2169
2170 default Object getQueryTrackTotalHitsValue() {
2171 Object value = propMap.get(QUERY_TRACK_TOTAL_HITS_VALUE);
2172 if (value == null) {
2173 final String v = getQueryTrackTotalHits();
2174 if (Constants.TRUE.equalsIgnoreCase(v)) {
2175 value = Boolean.TRUE;
2176 } else if (Constants.FALSE.equalsIgnoreCase(v)) {
2177 value = Boolean.FALSE;
2178 } else {
2179 try {
2180 value = DfTypeUtil.toInteger(v);
2181 } catch (final NumberFormatException e) {
2182 value = StringUtil.EMPTY;
2183 }
2184 }
2185 propMap.put(QUERY_TRACK_TOTAL_HITS_VALUE, value);
2186 }
2187 return value;
2188 }
2189
2190 Integer getProcessorsAsInteger();
2191
2192 default int availableProcessors() {
2193 final int num = getProcessorsAsInteger();
2194 if (num > 0) {
2195 return num;
2196 }
2197 return Runtime.getRuntime().availableProcessors();
2198 }
2199
2200 Integer getCrawlerHttpThreadPoolSizeAsInteger();
2201
2202 default int getCrawlerHttpProcessors() {
2203 final int num = getCrawlerHttpThreadPoolSizeAsInteger();
2204 if (num > 0) {
2205 return num;
2206 }
2207 return Runtime.getRuntime().availableProcessors();
2208 }
2209
2210 String getPluginVersionFilter();
2211
2212 default boolean isTargetPluginVersion(final String version) {
2213 final Pattern pattern;
2214 if (StringUtil.isBlank(getPluginVersionFilter())) {
2215 pattern = Pattern.compile("^" + Pattern.quote(ComponentUtil.getSystemHelper().getProductVersion()) + ".*");
2216 } else {
2217 pattern = Pattern.compile(getPluginVersionFilter());
2218 }
2219 return pattern.matcher(version).matches();
2220 }
2221
2222 String getQueryHighlightBoundaryChars();
2223
2224 default char[] getQueryHighlightBoundaryCharsAsArray() {
2225 final int[] values = getCrawlerDocumentCharsAsArray(QUERY_HIGHLIGHT_BOUNDARY_CHARS, getQueryHighlightBoundaryChars());
2226 final char[] chars = new char[values.length];
2227 for (int i = 0; i < values.length; i++) {
2228 chars[i] = (char) values[i];
2229 }
2230 return chars;
2231 }
2232
2233 String getQueryHighlightTerminalChars();
2234
2235 default int[] getQueryHighlightTerminalCharsAsArray() {
2236 return getCrawlerDocumentCharsAsArray(QUERY_HIGHLIGHT_TERMINAL_CHARS, getQueryHighlightTerminalChars());
2237 }
2238
2239 String getHttpFileuploadMaxSize();
2240
2241 default Long getHttpFileuploadMaxSizeAsLong() {
2242 final String value = getHttpFileuploadMaxSize();
2243 return value != null ? DfTypeUtil.toLong(value) : null;
2244 }
2245
2246 String getHttpFileuploadThresholdSize();
2247
2248 default Long getHttpFileuploadThresholdSizeAsLong() {
2249 final String value = getHttpFileuploadThresholdSize();
2250 return value != null ? DfTypeUtil.toLong(value) : null;
2251 }
2252
2253 String getPasswordInvalidAdminPasswords();
2254
2255 default boolean isValidAdminPassword(final String password) {
2256 return !split(getPasswordInvalidAdminPasswords(), "\n")
2257 .get(stream -> stream.map(String::trim).filter(StringUtil::isNotEmpty).anyMatch(s -> s.equals(password)));
2258 }
2259
2260 Integer getPasswordMinLengthAsInteger();
2261
2262 boolean isPasswordRequireUppercase();
2263
2264 boolean isPasswordRequireLowercase();
2265
2266 boolean isPasswordRequireDigit();
2267
2268 boolean isPasswordRequireSpecialChar();
2269
2270 String getSearchlogRequestHeaders();
2271
2272 default String[] getSearchlogRequestHeadersAsArray() {
2273 return split(getSearchlogRequestHeaders(), ",")
2274 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).toArray(n -> new String[n]));
2275 }
2276
2277 String getApiPingSearchEngineFields();
2278
2279 default Set<String> getApiPingEsFieldSet() {
2280 Set<String> value = (Set<String>) propMap.get(API_PING_SEARCH_ENGINE_FIELD_SET);
2281 if (value == null) {
2282 value = split(getApiPingSearchEngineFields(), ",")
2283 .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.toSet()));
2284 propMap.put(API_PING_SEARCH_ENGINE_FIELD_SET, value);
2285 }
2286 return value;
2287 }
2288
2289 String get(String propertyKey);
2290
2291 String getSearchEngineType();
2292
2293 default String getFesenType() {
2294 final String value = getSearchEngineType();
2295 if (value != null) {
2296 return value;
2297 }
2298 return get("elasticsearch.type");
2299 }
2300
2301 String getSearchEngineHttpUrl();
2302
2303 default String getFesenHttpUrl() {
2304 final String value = getSearchEngineHttpUrl();
2305 if (value != null) {
2306 return value;
2307 }
2308 return get("elasticsearch.http.url");
2309 }
2310
2311 String getSearchEngineHttpSslCertificateAuthorities();
2312
2313 default String getFesenHttpSslCertificateAuthorities() {
2314 final String value = getSearchEngineHttpSslCertificateAuthorities();
2315 if (value != null) {
2316 return value;
2317 }
2318 return get("elasticsearch.http.ssl.certificate_authorities");
2319 }
2320
2321 String getSearchEngineUsername();
2322
2323 default String getFesenUsername() {
2324 final String value = getSearchEngineUsername();
2325 if (value != null) {
2326 return value;
2327 }
2328 return get("elasticsearch.username");
2329 }
2330
2331 String getSearchEnginePassword();
2332
2333 default String getFesenPassword() {
2334 final String value = getSearchEnginePassword();
2335 if (value != null) {
2336 return value;
2337 }
2338 return get("elasticsearch.password");
2339 }
2340
2341 Integer getAsInteger(String propertyKey);
2342
2343 Integer getSearchEngineHeartbeatIntervalAsInteger();
2344
2345 default long getFesenHeartbeatInterval() {
2346 Integer value = getSearchEngineHeartbeatIntervalAsInteger();
2347 if (value != null) {
2348 return value.longValue();
2349 }
2350 value = getAsInteger("elasticsearch.heartbeat_interval");
2351 if (value != null) {
2352 return value.longValue();
2353 }
2354 return 10000L;
2355 }
2356
2357
2358
2359
2360 String RATE_LIMIT_WHITELIST_IPS_SET = "rateLimitWhitelistIpsSet";
2361
2362 String RATE_LIMIT_BLOCKED_IPS_SET = "rateLimitBlockedIpsSet";
2363
2364 String getRateLimitWhitelistIps();
2365
2366 default Set<String> getRateLimitWhitelistIpsAsSet() {
2367 @SuppressWarnings("unchecked")
2368 Set<String> set = (Set<String>) propMap.get(RATE_LIMIT_WHITELIST_IPS_SET);
2369 if (set == null) {
2370 set = split(getRateLimitWhitelistIps(), ",")
2371 .get(stream -> stream.map(String::trim).filter(StringUtil::isNotEmpty).collect(Collectors.toSet()));
2372 propMap.put(RATE_LIMIT_WHITELIST_IPS_SET, set);
2373 }
2374 return set;
2375 }
2376
2377 String getRateLimitBlockedIps();
2378
2379 default Set<String> getRateLimitBlockedIpsAsSet() {
2380 @SuppressWarnings("unchecked")
2381 Set<String> set = (Set<String>) propMap.get(RATE_LIMIT_BLOCKED_IPS_SET);
2382 if (set == null) {
2383 set = split(getRateLimitBlockedIps(), ",")
2384 .get(stream -> stream.map(String::trim).filter(StringUtil::isNotEmpty).collect(Collectors.toSet()));
2385 propMap.put(RATE_LIMIT_BLOCKED_IPS_SET, set);
2386 }
2387 return set;
2388 }
2389
2390 String RATE_LIMIT_TRUSTED_PROXIES_SET = "rateLimitTrustedProxiesSet";
2391
2392 String getRateLimitTrustedProxies();
2393
2394 default Set<String> getRateLimitTrustedProxiesAsSet() {
2395 @SuppressWarnings("unchecked")
2396 Set<String> set = (Set<String>) propMap.get(RATE_LIMIT_TRUSTED_PROXIES_SET);
2397 if (set == null) {
2398 set = split(getRateLimitTrustedProxies(), ",")
2399 .get(stream -> stream.map(String::trim).filter(StringUtil::isNotEmpty).collect(Collectors.toSet()));
2400 propMap.put(RATE_LIMIT_TRUSTED_PROXIES_SET, set);
2401 }
2402 return set;
2403 }
2404 }