1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.dict;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.Date;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.annotation.PostConstruct;
27
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.codelibs.core.io.FileUtil;
31 import org.codelibs.curl.CurlResponse;
32 import org.codelibs.fesen.runner.net.FesenCurl;
33 import org.codelibs.fess.Constants;
34 import org.codelibs.fess.util.ComponentUtil;
35 import org.dbflute.optional.OptionalEntity;
36
37 public class DictionaryManager {
38 private static final Logger logger = LogManager.getLogger(DictionaryManager.class);
39
40 protected List<DictionaryCreator> creatorList = new ArrayList<>();
41
42 @PostConstruct
43 public void init() {
44 if (logger.isDebugEnabled()) {
45 logger.debug("Initialize {}", this.getClass().getSimpleName());
46 }
47 creatorList.forEach(creator -> {
48 creator.setDictionaryManager(this);
49 });
50 }
51
52 public DictionaryFile<? extends DictionaryItem>[] getDictionaryFiles() {
53 try (CurlResponse response = ComponentUtil.getCurlHelper().get("/_configsync/file").param("fields", "path,@timestamp")
54 .param("size", ComponentUtil.getFessConfig().getPageDictionaryMaxFetchSize()).execute()) {
55 final Map<String, Object> contentMap = response.getContent(FesenCurl.jsonParser());
56 @SuppressWarnings("unchecked")
57 final List<Map<String, Object>> fileList = (List<Map<String, Object>>) contentMap.get("file");
58 return fileList.stream().map(fileMap -> {
59 try {
60 final String path = fileMap.get("path").toString();
61 final Date timestamp =
62 new SimpleDateFormat(Constants.DATE_FORMAT_ISO_8601_EXTEND_UTC).parse(fileMap.get("@timestamp").toString());
63 for (final DictionaryCreator creator : creatorList) {
64 final DictionaryFile<? extends DictionaryItem> file = creator.create(path, timestamp);
65 if (file != null) {
66 return file;
67 }
68 }
69 } catch (final Exception e) {
70 logger.warn("Failed to load {}", fileMap, e);
71 }
72 return null;
73 }).filter(file -> file != null).toArray(n -> new DictionaryFile<?>[n]);
74 } catch (final IOException e) {
75 throw new DictionaryException("Failed to access dictionaries", e);
76 }
77 }
78
79 public OptionalEntity<DictionaryFile<? extends DictionaryItem>> getDictionaryFile(final String id) {
80 for (final DictionaryFile<? extends DictionaryItem> dictFile : getDictionaryFiles()) {
81 if (dictFile.getId().equals(id)) {
82 return OptionalEntity.of(dictFile);
83 }
84 }
85 return OptionalEntity.empty();
86 }
87
88 public void store(final DictionaryFile<? extends DictionaryItem> dictFile, final File file) {
89 getDictionaryFile(dictFile.getId()).ifPresent(currentFile -> {
90 if (currentFile.getTimestamp().getTime() > dictFile.getTimestamp().getTime()) {
91 throw new DictionaryException(dictFile.getPath() + " was updated.");
92 }
93
94
95 try (CurlResponse response = ComponentUtil.getCurlHelper().post("/_configsync/file").param("path", dictFile.getPath())
96 .body(FileUtil.readUTF8(file)).execute()) {
97 final Map<String, Object> contentMap = response.getContent(FesenCurl.jsonParser());
98 if (!Constants.TRUE.equalsIgnoreCase(contentMap.get("acknowledged").toString())) {
99 throw new DictionaryException("Failed to update " + dictFile.getPath());
100 }
101 } catch (final IOException e) {
102 throw new DictionaryException("Failed to update " + dictFile.getPath(), e);
103 }
104
105 }).orElse(() -> {
106 throw new DictionaryException(dictFile.getPath() + " does not exist.");
107 });
108 }
109
110 public CurlResponse getContentResponse(final DictionaryFile<? extends DictionaryItem> dictFile) {
111 return ComponentUtil.getCurlHelper().get("/_configsync/file").param("path", dictFile.getPath()).execute();
112 }
113
114 public void addCreator(final DictionaryCreator creator) {
115 creatorList.add(creator);
116 }
117
118 }