1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.helper;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.TimeUnit;
24 import java.util.regex.Pattern;
25
26 import org.apache.logging.log4j.LogManager;
27 import org.apache.logging.log4j.Logger;
28 import org.codelibs.core.lang.StringUtil;
29 import org.codelibs.fess.Constants;
30 import org.codelibs.fess.app.service.DataConfigService;
31 import org.codelibs.fess.app.service.FileConfigService;
32 import org.codelibs.fess.app.service.WebConfigService;
33 import org.codelibs.fess.mylasta.direction.FessConfig;
34 import org.codelibs.fess.opensearch.config.exbhv.DataConfigBhv;
35 import org.codelibs.fess.opensearch.config.exbhv.FailureUrlBhv;
36 import org.codelibs.fess.opensearch.config.exbhv.FileConfigBhv;
37 import org.codelibs.fess.opensearch.config.exbhv.WebConfigBhv;
38 import org.codelibs.fess.opensearch.config.exentity.CrawlingConfig;
39 import org.codelibs.fess.opensearch.config.exentity.CrawlingConfig.ConfigName;
40 import org.codelibs.fess.opensearch.config.exentity.CrawlingConfig.ConfigType;
41 import org.codelibs.fess.opensearch.config.exentity.CrawlingConfig.Param.Config;
42 import org.codelibs.fess.opensearch.config.exentity.DataConfig;
43 import org.codelibs.fess.opensearch.config.exentity.FailureUrl;
44 import org.codelibs.fess.opensearch.config.exentity.FileConfig;
45 import org.codelibs.fess.opensearch.config.exentity.WebConfig;
46 import org.codelibs.fess.util.ComponentUtil;
47 import org.dbflute.cbean.result.ListResultBean;
48 import org.dbflute.optional.OptionalEntity;
49 import org.dbflute.optional.OptionalThing;
50
51 import com.google.common.cache.Cache;
52 import com.google.common.cache.CacheBuilder;
53
54 import jakarta.annotation.PostConstruct;
55
56
57
58
59
60
61 public class CrawlingConfigHelper {
62
63
64
65
66 public CrawlingConfigHelper() {
67
68 }
69
70 private static final Logger logger = LogManager.getLogger(CrawlingConfigHelper.class);
71
72
73
74
75 protected final Map<String, CrawlingConfig> crawlingConfigMap = new ConcurrentHashMap<>();
76
77
78
79
80 protected int count = 1;
81
82
83
84
85 protected Cache<String, CrawlingConfig> crawlingConfigCache;
86
87
88
89
90
91
92 @PostConstruct
93 public void init() {
94 if (logger.isDebugEnabled()) {
95 logger.debug("Initializing {}", this.getClass().getSimpleName());
96 }
97 crawlingConfigCache = CacheBuilder.newBuilder().maximumSize(100).expireAfterWrite(10, TimeUnit.MINUTES).build();
98 }
99
100
101
102
103
104
105
106
107 public ConfigType getConfigType(final String configId) {
108 if (configId == null || configId.length() < 2) {
109 return null;
110 }
111 final String configType = configId.substring(0, 1);
112 if (ConfigType.WEB.getTypePrefix().equals(configType)) {
113 return ConfigType.WEB;
114 }
115 if (ConfigType.FILE.getTypePrefix().equals(configType)) {
116 return ConfigType.FILE;
117 }
118 if (ConfigType.DATA.getTypePrefix().equals(configType)) {
119 return ConfigType.DATA;
120 }
121 return null;
122 }
123
124
125
126
127
128
129
130
131
132 protected String getId(final String configId) {
133 if (configId == null || configId.length() < 2) {
134 return null;
135 }
136 return configId.substring(1);
137 }
138
139
140
141
142
143
144
145
146
147 public CrawlingConfig getCrawlingConfig(final String configId) {
148 try {
149 return crawlingConfigCache.get(configId, () -> {
150 final ConfigType configType = getConfigType(configId);
151 if (configType == null) {
152 return null;
153 }
154 final String id = getId(configId);
155 if (id == null) {
156 return null;
157 }
158 return switch (configType) {
159 case WEB -> {
160 final WebConfigService webConfigService = ComponentUtil.getComponent(WebConfigService.class);
161 yield webConfigService.getWebConfig(id).get();
162 }
163 case FILE -> {
164 final FileConfigService fileConfigService = ComponentUtil.getComponent(FileConfigService.class);
165 yield fileConfigService.getFileConfig(id).get();
166 }
167 case DATA -> {
168 final DataConfigService dataConfigService = ComponentUtil.getComponent(DataConfigService.class);
169 yield dataConfigService.getDataConfig(id).get();
170 }
171 default -> null;
172 };
173 });
174 } catch (final Exception e) {
175 logger.warn("Failed to access a crawling config cache: {}", configId, e);
176 return null;
177 }
178 }
179
180
181
182
183
184
185
186
187 public OptionalThing<String> getPipeline(final String configId) {
188 final CrawlingConfig config = getCrawlingConfig(configId);
189 if (config == null) {
190 return OptionalThing.empty();
191 }
192 final String pipeline = config.getConfigParameterMap(ConfigName.CONFIG).get(Config.PIPELINE);
193 if (StringUtil.isBlank(pipeline)) {
194 return OptionalThing.empty();
195 }
196 return OptionalThing.of(pipeline);
197 }
198
199
200
201
202
203 public void refresh() {
204 crawlingConfigCache.invalidateAll();
205 }
206
207
208
209
210
211
212
213
214
215 public synchronized String store(final String sessionId, final CrawlingConfig crawlingConfig) {
216 final String sessionCountId = sessionId + "-" + count;
217 crawlingConfigMap.put(sessionCountId, crawlingConfig);
218 count++;
219 return sessionCountId;
220 }
221
222
223
224
225
226
227 public void remove(final String sessionCountId) {
228 crawlingConfigMap.remove(sessionCountId);
229 }
230
231
232
233
234
235
236
237 public CrawlingConfig get(final String sessionCountId) {
238 return crawlingConfigMap.get(sessionCountId);
239 }
240
241
242
243
244
245
246
247
248 public List<WebConfig> getAllWebConfigList() {
249 return getAllWebConfigList(true, true, true, null);
250 }
251
252
253
254
255
256
257
258
259 public List<WebConfig> getWebConfigListByIds(final List<String> idList) {
260 if (idList == null) {
261 return getAllWebConfigList();
262 }
263 return getAllWebConfigList(true, true, false, idList);
264 }
265
266
267
268
269
270
271
272
273
274
275 public List<WebConfig> getAllWebConfigList(final boolean withLabelType, final boolean withRoleType, final boolean available,
276 final List<String> idList) {
277 return ComponentUtil.getComponent(WebConfigBhv.class).selectList(cb -> {
278 if (available) {
279 cb.query().setAvailable_Equal(Constants.T);
280 }
281 if (idList != null) {
282 cb.query().setId_InScope(idList);
283 }
284 cb.query().setName_NotEqual(ComponentUtil.getFessConfig().getFormAdminDefaultTemplateName());
285 cb.query().addOrderBy_SortOrder_Asc();
286 cb.query().addOrderBy_Name_Asc();
287 cb.fetchFirst(ComponentUtil.getFessConfig().getPageWebConfigMaxFetchSizeAsInteger());
288 });
289 }
290
291
292
293
294
295
296
297
298 public List<FileConfig> getAllFileConfigList() {
299 return getAllFileConfigList(true, true, true, null);
300 }
301
302
303
304
305
306
307
308
309 public List<FileConfig> getFileConfigListByIds(final List<String> idList) {
310 if (idList == null) {
311 return getAllFileConfigList();
312 }
313 return getAllFileConfigList(true, true, false, idList);
314 }
315
316
317
318
319
320
321
322
323
324
325 public List<FileConfig> getAllFileConfigList(final boolean withLabelType, final boolean withRoleType, final boolean available,
326 final List<String> idList) {
327 return ComponentUtil.getComponent(FileConfigBhv.class).selectList(cb -> {
328 if (available) {
329 cb.query().setAvailable_Equal(Constants.T);
330 }
331 if (idList != null) {
332 cb.query().setId_InScope(idList);
333 }
334 cb.query().setName_NotEqual(ComponentUtil.getFessConfig().getFormAdminDefaultTemplateName());
335 cb.query().addOrderBy_SortOrder_Asc();
336 cb.query().addOrderBy_Name_Asc();
337 cb.fetchFirst(ComponentUtil.getFessConfig().getPageFileConfigMaxFetchSizeAsInteger());
338 });
339 }
340
341
342
343
344
345
346
347
348 public List<DataConfig> getAllDataConfigList() {
349 return getAllDataConfigList(true, true, true, null);
350 }
351
352
353
354
355
356
357
358
359 public List<DataConfig> getDataConfigListByIds(final List<String> idList) {
360 if (idList == null) {
361 return getAllDataConfigList();
362 }
363 return getAllDataConfigList(true, true, false, idList);
364 }
365
366
367
368
369
370
371
372
373
374
375 public List<DataConfig> getAllDataConfigList(final boolean withLabelType, final boolean withRoleType, final boolean available,
376 final List<String> idList) {
377 return ComponentUtil.getComponent(DataConfigBhv.class).selectList(cb -> {
378 if (available) {
379 cb.query().setAvailable_Equal(Constants.T);
380 }
381 if (idList != null) {
382 cb.query().setId_InScope(idList);
383 }
384 cb.query().setName_NotEqual(ComponentUtil.getFessConfig().getFormAdminDefaultTemplateName());
385 cb.query().addOrderBy_SortOrder_Asc();
386 cb.query().addOrderBy_Name_Asc();
387 cb.fetchFirst(ComponentUtil.getFessConfig().getPageDataConfigMaxFetchSizeAsInteger());
388 });
389 }
390
391
392
393
394
395
396
397
398
399 public List<String> getExcludedUrlList(final String configId) {
400 final FessConfig fessConfig = ComponentUtil.getFessConfig();
401 final int failureCount = fessConfig.getFailureCountThreshold();
402 final String ignoreFailureType = fessConfig.getIgnoreFailureType();
403
404 if (failureCount < 0) {
405 return Collections.emptyList();
406 }
407
408 final int count = failureCount;
409 final ListResultBean<FailureUrl> list = ComponentUtil.getComponent(FailureUrlBhv.class).selectList(cb -> {
410 cb.query().setConfigId_Equal(configId);
411 cb.query().setErrorCount_GreaterEqual(count);
412 cb.fetchFirst(fessConfig.getPageFailureUrlMaxFetchSizeAsInteger());
413 });
414 if (list.isEmpty()) {
415 return Collections.emptyList();
416 }
417
418 Pattern pattern = null;
419 if (StringUtil.isNotBlank(ignoreFailureType)) {
420 pattern = Pattern.compile(ignoreFailureType);
421 }
422 final List<String> urlList = new ArrayList<>();
423 for (final FailureUrl failureUrl : list) {
424 if (pattern != null) {
425 if (!pattern.matcher(failureUrl.getErrorName()).matches()) {
426 urlList.add(failureUrl.getUrl());
427 }
428 } else {
429 urlList.add(failureUrl.getUrl());
430 }
431 }
432 return urlList;
433 }
434
435
436
437
438
439
440
441
442 public OptionalEntity<CrawlingConfig> getDefaultConfig(final ConfigType configType) {
443 if (configType == null) {
444 return OptionalEntity.empty();
445 }
446
447 final String name = ComponentUtil.getFessConfig().getFormAdminDefaultTemplateName();
448
449 return switch (configType) {
450 case WEB -> {
451 final WebConfigService webConfigService = ComponentUtil.getComponent(WebConfigService.class);
452 yield webConfigService.getWebConfigByName(name).map(o -> (CrawlingConfig) o);
453 }
454 case FILE -> {
455 final FileConfigService fileConfigService = ComponentUtil.getComponent(FileConfigService.class);
456 yield fileConfigService.getFileConfigByName(name).map(o -> (CrawlingConfig) o);
457 }
458 case DATA -> {
459 final DataConfigService dataConfigService = ComponentUtil.getComponent(DataConfigService.class);
460 yield dataConfigService.getDataConfigByName(name).map(o -> (CrawlingConfig) o);
461 }
462 default -> OptionalEntity.empty();
463 };
464 }
465 }