View Javadoc
1   /*
2    * Copyright 2012-2017 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.dict;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.text.SimpleDateFormat;
22  import java.util.ArrayList;
23  import java.util.Date;
24  import java.util.List;
25  import java.util.Map;
26  
27  import javax.annotation.PostConstruct;
28  
29  import org.codelibs.core.io.FileUtil;
30  import org.codelibs.elasticsearch.runner.net.Curl;
31  import org.codelibs.elasticsearch.runner.net.CurlResponse;
32  import org.codelibs.fess.Constants;
33  import org.codelibs.fess.util.ComponentUtil;
34  import org.codelibs.fess.util.ResourceUtil;
35  import org.dbflute.optional.OptionalEntity;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  public class DictionaryManager {
40      private static final Logger logger = LoggerFactory.getLogger(DictionaryManager.class);
41  
42      protected List<DictionaryCreator> creatorList = new ArrayList<>();
43  
44      @PostConstruct
45      public void init() {
46          creatorList.forEach(creator -> {
47              creator.setDictionaryManager(this);
48          });
49      }
50  
51      public DictionaryFile<? extends DictionaryItem>[] getDictionaryFiles() {
52          try (CurlResponse response =
53                  Curl.get(ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/file").header("Content-Type", "application/json")
54                          .param("fields", "path,@timestamp").param("size", ComponentUtil.getFessConfig().getPageDictionaryMaxFetchSize())
55                          .execute()) {
56              final Map<String, Object> contentMap = response.getContentAsMap();
57              @SuppressWarnings("unchecked")
58              final List<Map<String, Object>> fileList = (List<Map<String, Object>>) contentMap.get("file");
59              return fileList
60                      .stream()
61                      .map(fileMap -> {
62                          try {
63                              final String path = fileMap.get("path").toString();
64                              final Date timestamp =
65                                      new SimpleDateFormat(Constants.DATE_FORMAT_ISO_8601_EXTEND_UTC).parse(fileMap.get("@timestamp")
66                                              .toString());
67                              for (final DictionaryCreator creator : creatorList) {
68                                  final DictionaryFile<? extends DictionaryItem> file = creator.create(path, timestamp);
69                                  if (file != null) {
70                                      return file;
71                                  }
72                              }
73                          } catch (final Exception e) {
74                              logger.warn("Failed to load " + fileMap, e);
75                          }
76                          return null;
77                      }).filter(file -> file != null).toArray(n -> new DictionaryFile<?>[n]);
78          } catch (final IOException e) {
79              throw new DictionaryException("Failed to access dictionaries", e);
80          }
81      }
82  
83      public OptionalEntity<DictionaryFile<? extends DictionaryItem>> getDictionaryFile(final String id) {
84          for (final DictionaryFile<? extends DictionaryItem> dictFile : getDictionaryFiles()) {
85              if (dictFile.getId().equals(id)) {
86                  return OptionalEntity.of(dictFile);
87              }
88          }
89          return OptionalEntity.empty();
90      }
91  
92      public void store(final DictionaryFile<? extends DictionaryItem> dictFile, final File file) {
93          getDictionaryFile(dictFile.getId()).ifPresent(currentFile -> {
94              if (currentFile.getTimestamp().getTime() > dictFile.getTimestamp().getTime()) {
95                  throw new DictionaryException(dictFile.getPath() + " was updated.");
96              }
97  
98              // TODO use stream
99                  try (CurlResponse response =
100                         Curl.post(ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/file").header("Content-Type", "application/json")
101                                 .param("path", dictFile.getPath()).body(FileUtil.readUTF8(file)).execute()) {
102                     final Map<String, Object> contentMap = response.getContentAsMap();
103                     if (!Constants.TRUE.equalsIgnoreCase(contentMap.get("acknowledged").toString())) {
104                         throw new DictionaryException("Failed to update " + dictFile.getPath());
105                     }
106                 } catch (final IOException e) {
107                     throw new DictionaryException("Failed to update " + dictFile.getPath(), e);
108                 }
109 
110             }).orElse(() -> {
111             throw new DictionaryException(dictFile.getPath() + " does not exist.");
112         });
113     }
114 
115     public InputStream getContentInputStream(final DictionaryFile<? extends DictionaryItem> dictFile) {
116         try {
117             return Curl.get(ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/file").header("Content-Type", "application/json")
118                     .param("path", dictFile.getPath()).execute().getContentAsStream();
119         } catch (final IOException e) {
120             throw new DictionaryException("Failed to access " + dictFile.getPath(), e);
121         }
122     }
123 
124     public void addCreator(final DictionaryCreator creator) {
125         creatorList.add(creator);
126     }
127 
128 }